EffectHal: Support retrieving worker thread tid am: 7d5eb5c837

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

Change-Id: Ib55ea0e45eafa42a92ff1cf94dae53d387fcbdfc
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/OWNERS b/OWNERS
index 3a1a038..a53d83e 100644
--- a/OWNERS
+++ b/OWNERS
@@ -9,6 +9,3 @@
 
 # historical/backup
 maco@google.com
-
-# vts tests
-guangzhu@google.com
diff --git a/audio/OWNERS b/audio/OWNERS
new file mode 100644
index 0000000..ede448c
--- /dev/null
+++ b/audio/OWNERS
@@ -0,0 +1 @@
+per-file README.md = elaurent@google.com,mnaganov@google.com
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 0b5b993..4e50b7a 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -33,7 +33,7 @@
         "android/hardware/audio/common/SourceMetadata.aidl",
     ],
     imports: [
-        "android.media.audio.common.types-V1",
+        "android.media.audio.common.types-V2",
     ],
     stability: "vintf",
     backend: {
@@ -49,12 +49,9 @@
             ],
         },
         ndk: {
-            vndk: {
-                enabled: true,
-            },
             apex_available: [
                 "//apex_available:platform",
-                "com.android.bluetooth",
+                "com.android.btservices",
             ],
             min_sdk_version: "31",
         },
@@ -62,8 +59,136 @@
     versions_with_info: [
         {
             version: "1",
-            imports: ["android.media.audio.common.types-V1"],
+            imports: ["android.media.audio.common.types-V2"],
         },
+        // IMPORTANT: Update latest_android_hardware_audio_common every time you
+        // add the latest frozen version to versions_with_info
     ],
 
 }
+
+// Note: This should always be one version ahead of the last frozen version
+latest_android_hardware_audio_common = "android.hardware.audio.common-V1"
+
+// Modules that depend on android.hardware.audio.common directly can include
+// the following cc_defaults to avoid explicitly managing dependency versions
+// across many scattered files.
+cc_defaults {
+    name: "latest_android_hardware_audio_common_cpp_static",
+    static_libs: [
+        latest_android_hardware_audio_common + "-cpp",
+    ],
+}
+
+cc_defaults {
+    name: "latest_android_hardware_audio_common_ndk_static",
+    static_libs: [
+        latest_android_hardware_audio_common + "-ndk",
+    ],
+}
+
+aidl_interface {
+    name: "android.hardware.audio.core",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/audio/core/AudioPatch.aidl",
+        "android/hardware/audio/core/AudioRoute.aidl",
+        "android/hardware/audio/core/IConfig.aidl",
+        "android/hardware/audio/core/IModule.aidl",
+        "android/hardware/audio/core/IStreamIn.aidl",
+        "android/hardware/audio/core/IStreamOut.aidl",
+        "android/hardware/audio/core/MmapBufferDescriptor.aidl",
+        "android/hardware/audio/core/ModuleDebug.aidl",
+        "android/hardware/audio/core/StreamDescriptor.aidl",
+        "android/hardware/audio/core/SurroundSoundConfig.aidl",
+    ],
+    imports: [
+        "android.hardware.common-V2",
+        "android.hardware.common.fmq-V1",
+        "android.hardware.audio.common-V1",
+        "android.media.audio.common.types-V2",
+    ],
+    stability: "vintf",
+    backend: {
+        // The C++ backend is disabled transitively due to use of FMQ.
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+    },
+    versions_with_info: [
+        // IMPORTANT: Update latest_android_hardware_audio_core every time you
+        // add the latest frozen version to versions_with_info
+    ],
+}
+
+// Note: This should always be one version ahead of the last frozen version
+latest_android_hardware_audio_core = "android.hardware.audio.core-V1"
+
+// Modules that depend on android.hardware.audio.core directly can include
+// the following cc_defaults to avoid explicitly managing dependency versions
+// across many scattered files.
+cc_defaults {
+    name: "latest_android_hardware_audio_core_ndk_shared",
+    shared_libs: [
+        latest_android_hardware_audio_core + "-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "latest_android_hardware_audio_core_ndk_static",
+    static_libs: [
+        latest_android_hardware_audio_core + "-ndk",
+    ],
+}
+
+aidl_interface {
+    name: "android.hardware.audio.effect",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/audio/effect/Capability.aidl",
+        "android/hardware/audio/effect/CommandId.aidl",
+        "android/hardware/audio/effect/Descriptor.aidl",
+        "android/hardware/audio/effect/Equalizer.aidl",
+        "android/hardware/audio/effect/Flags.aidl",
+        "android/hardware/audio/effect/IEffect.aidl",
+        "android/hardware/audio/effect/IFactory.aidl",
+        "android/hardware/audio/effect/Parameter.aidl",
+        "android/hardware/audio/effect/Processing.aidl",
+        "android/hardware/audio/effect/State.aidl",
+    ],
+    imports: [
+        "android.hardware.common-V2",
+        "android.hardware.common.fmq-V1",
+        "android.hardware.audio.common-V1",
+        "android.media.audio.common.types-V2",
+    ],
+    stability: "vintf",
+    backend: {
+        // The C++ backend is disabled transitively due to use of FMQ.
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+    },
+}
+
+latest_android_hardware_audio_effect = "android.hardware.audio.effect-V1"
+
+cc_defaults {
+    name: "latest_android_hardware_audio_effect_ndk_shared",
+    shared_libs: [
+        latest_android_hardware_audio_effect + "-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "latest_android_hardware_audio_effect_ndk_static",
+    static_libs: [
+        latest_android_hardware_audio_effect + "-ndk",
+    ],
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/AudioPatch.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/AudioPatch.aidl
new file mode 100644
index 0000000..078b5ea
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/AudioPatch.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable AudioPatch {
+  int id;
+  int[] sourcePortConfigIds;
+  int[] sinkPortConfigIds;
+  int minimumStreamBufferSizeFrames;
+  int[] latenciesMs;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/AudioRoute.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/AudioRoute.aidl
new file mode 100644
index 0000000..deeef87
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/AudioRoute.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable AudioRoute {
+  int[] sourcePortIds;
+  int sinkPortId;
+  boolean isExclusive;
+}
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
new file mode 100644
index 0000000..163b7a0
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@VintfStability
+interface IConfig {
+  android.hardware.audio.core.SurroundSoundConfig getSurroundSoundConfig();
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
new file mode 100644
index 0000000..a8bbb15
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@VintfStability
+interface IModule {
+  void setModuleDebug(in android.hardware.audio.core.ModuleDebug debug);
+  android.media.audio.common.AudioPort connectExternalDevice(in android.media.audio.common.AudioPort templateIdAndAdditionalData);
+  void disconnectExternalDevice(int portId);
+  android.hardware.audio.core.AudioPatch[] getAudioPatches();
+  android.media.audio.common.AudioPort getAudioPort(int portId);
+  android.media.audio.common.AudioPortConfig[] getAudioPortConfigs();
+  android.media.audio.common.AudioPort[] getAudioPorts();
+  android.hardware.audio.core.AudioRoute[] getAudioRoutes();
+  android.hardware.audio.core.AudioRoute[] getAudioRoutesForAudioPort(int portId);
+  android.hardware.audio.core.IModule.OpenInputStreamReturn openInputStream(in android.hardware.audio.core.IModule.OpenInputStreamArguments args);
+  android.hardware.audio.core.IModule.OpenOutputStreamReturn openOutputStream(in android.hardware.audio.core.IModule.OpenOutputStreamArguments args);
+  android.hardware.audio.core.AudioPatch setAudioPatch(in android.hardware.audio.core.AudioPatch requested);
+  boolean setAudioPortConfig(in android.media.audio.common.AudioPortConfig requested, out android.media.audio.common.AudioPortConfig suggested);
+  void resetAudioPatch(int patchId);
+  void resetAudioPortConfig(int portConfigId);
+  @VintfStability
+  parcelable OpenInputStreamArguments {
+    int portConfigId;
+    android.hardware.audio.common.SinkMetadata sinkMetadata;
+    long bufferSizeFrames;
+  }
+  @VintfStability
+  parcelable OpenInputStreamReturn {
+    android.hardware.audio.core.IStreamIn stream;
+    android.hardware.audio.core.StreamDescriptor desc;
+  }
+  @VintfStability
+  parcelable OpenOutputStreamArguments {
+    int portConfigId;
+    android.hardware.audio.common.SourceMetadata sourceMetadata;
+    @nullable android.media.audio.common.AudioOffloadInfo offloadInfo;
+    long bufferSizeFrames;
+  }
+  @VintfStability
+  parcelable OpenOutputStreamReturn {
+    android.hardware.audio.core.IStreamOut stream;
+    android.hardware.audio.core.StreamDescriptor desc;
+  }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
new file mode 100644
index 0000000..d5ab3e8
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@VintfStability
+interface IStreamIn {
+  void close();
+  void updateMetadata(in android.hardware.audio.common.SinkMetadata sinkMetadata);
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl
new file mode 100644
index 0000000..3021d94
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@VintfStability
+interface IStreamOut {
+  void close();
+  void updateMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/MmapBufferDescriptor.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/MmapBufferDescriptor.aidl
new file mode 100644
index 0000000..6ea1c69
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/MmapBufferDescriptor.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable MmapBufferDescriptor {
+  android.hardware.common.Ashmem sharedMemory;
+  long burstSizeFrames;
+  int flags;
+  const int FLAG_INDEX_APPLICATION_SHAREABLE = 0;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ModuleDebug.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ModuleDebug.aidl
new file mode 100644
index 0000000..80ee185
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ModuleDebug.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable ModuleDebug {
+  boolean simulateDeviceConnections;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/StreamDescriptor.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/StreamDescriptor.aidl
new file mode 100644
index 0000000..db1ac22
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/StreamDescriptor.aidl
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable StreamDescriptor {
+  android.hardware.common.fmq.MQDescriptor<android.hardware.audio.core.StreamDescriptor.Command,android.hardware.common.fmq.SynchronizedReadWrite> command;
+  android.hardware.common.fmq.MQDescriptor<android.hardware.audio.core.StreamDescriptor.Reply,android.hardware.common.fmq.SynchronizedReadWrite> reply;
+  int frameSizeBytes;
+  long bufferSizeFrames;
+  android.hardware.audio.core.StreamDescriptor.AudioBuffer audio;
+  const int COMMAND_BURST = 1;
+  @FixedSize @VintfStability
+  parcelable Position {
+    long frames;
+    long timeNs;
+  }
+  @FixedSize @VintfStability
+  parcelable Command {
+    int code;
+    int fmqByteCount;
+  }
+  @FixedSize @VintfStability
+  parcelable Reply {
+    int status;
+    int fmqByteCount;
+    android.hardware.audio.core.StreamDescriptor.Position observable;
+    android.hardware.audio.core.StreamDescriptor.Position hardware;
+    int latencyMs;
+  }
+  @VintfStability
+  union AudioBuffer {
+    android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> fmq;
+    android.hardware.audio.core.MmapBufferDescriptor mmap;
+  }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/SurroundSoundConfig.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/SurroundSoundConfig.aidl
new file mode 100644
index 0000000..08a1537
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/SurroundSoundConfig.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SurroundSoundConfig {
+  android.hardware.audio.core.SurroundSoundConfig.SurroundFormatFamily[] formatFamilies;
+  @VintfStability
+  parcelable SurroundFormatFamily {
+    android.media.audio.common.AudioFormatDescription primaryFormat;
+    android.media.audio.common.AudioFormatDescription[] subFormats;
+  }
+}
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
new file mode 100644
index 0000000..11acf5e
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union Capability {
+  android.hardware.audio.effect.Capability.VendorEffectCapability vendor;
+  android.hardware.audio.effect.Equalizer.Capability equalizer;
+  @VintfStability
+  parcelable VendorEffectCapability {
+    ParcelableHolder extension;
+  }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.aidl
new file mode 100644
index 0000000..79299ee
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.aidl
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@Backing(type="int") @VintfStability
+enum CommandId {
+  START = 0,
+  STOP = 1,
+  RESET = 2,
+  VENDOR_COMMAND_0 = 256,
+  VENDOR_COMMAND_1 = 257,
+  VENDOR_COMMAND_2 = 258,
+  VENDOR_COMMAND_3 = 259,
+  VENDOR_COMMAND_4 = 260,
+  VENDOR_COMMAND_5 = 261,
+  VENDOR_COMMAND_6 = 262,
+  VENDOR_COMMAND_7 = 263,
+  VENDOR_COMMAND_8 = 264,
+  VENDOR_COMMAND_9 = 265,
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
new file mode 100644
index 0000000..4707011
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+parcelable Descriptor {
+  android.hardware.audio.effect.Descriptor.Common common;
+  android.hardware.audio.effect.Capability capability;
+  const String EFFECT_TYPE_UUID_ENV_REVERB = "c2e5d5f0-94bd-4763-9cac-4e234d06839e";
+  const String EFFECT_TYPE_UUID_PRESET_REVERB = "47382d60-ddd8-11db-bf3a-0002a5d5c51b";
+  const String EFFECT_TYPE_UUID_EQUALIZER = "0bed4300-ddd6-11db-8f34-0002a5d5c51b";
+  const String EFFECT_TYPE_UUID_BASS_BOOST = "0634f220-ddd4-11db-a0fc-0002a5d5c51b";
+  const String EFFECT_TYPE_UUID_VIRTUALIZER = "37cc2c00-dddd-11db-8577-0002a5d5c51b";
+  const String EFFECT_TYPE_UUID_AGC = "0a8abfe0-654c-11e0-ba26-0002a5d5c51b";
+  const String EFFECT_TYPE_UUID_AEC = "7b491460-8d4d-11e0-bd61-0002a5d5c51b";
+  const String EFFECT_TYPE_UUID_NS = "58b4b260-8e06-11e0-aa8e-0002a5d5c51b";
+  const String EFFECT_TYPE_UUID_LOUDNESS_ENHANCER = "fe3199be-aed0-413f-87bb-11260eb63cf1";
+  const String EFFECT_TYPE_UUID_DYNAMICS_PROCESSING = "7261676f-6d75-7369-6364-28e2fd3ac39e";
+  const String EFFECT_TYPE_UUID_HAPTIC_GENERATOR = "1411e6d6-aecd-4021-a1cf-a6aceb0d71e5";
+  const String EFFECT_TYPE_UUID_SPATIALIZER = "ccd4cf09-a79d-46c2-9aae-06a1698d6c8f";
+  const String EFFECT_TYPE_UUID_VOLUME = "09e8ede0-ddde-11db-b4f6-0002a5d5c51b";
+  @VintfStability
+  parcelable Identity {
+    android.media.audio.common.AudioUuid type;
+    android.media.audio.common.AudioUuid uuid;
+    @nullable android.media.audio.common.AudioUuid proxy;
+    android.hardware.audio.effect.Flags flags;
+  }
+  @VintfStability
+  parcelable Common {
+    android.hardware.audio.effect.Descriptor.Identity id;
+    int cpuLoad;
+    int memoryUsage;
+    @utf8InCpp String name;
+    @utf8InCpp String implementor;
+  }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl
new file mode 100644
index 0000000..f7af300
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union Equalizer {
+  android.hardware.audio.effect.Equalizer.VendorExtension vendor;
+  android.hardware.audio.effect.Equalizer.BandLevel[] bandLevels;
+  int preset;
+  @VintfStability
+  parcelable VendorExtension {
+    ParcelableHolder extension;
+  }
+  @VintfStability
+  parcelable Capability {
+    ParcelableHolder extension;
+    android.hardware.audio.effect.Equalizer.BandFrequency[] bandFrequencies;
+    android.hardware.audio.effect.Equalizer.Preset[] presets;
+  }
+  @VintfStability
+  parcelable BandLevel {
+    int index;
+    int level;
+  }
+  @VintfStability
+  parcelable BandFrequency {
+    int index;
+    int min;
+    int max;
+  }
+  @VintfStability
+  parcelable Preset {
+    int index;
+    @utf8InCpp String name;
+  }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Flags.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Flags.aidl
new file mode 100644
index 0000000..285ff18
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Flags.aidl
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+parcelable Flags {
+  android.hardware.audio.effect.Flags.Type type = android.hardware.audio.effect.Flags.Type.INSERT;
+  android.hardware.audio.effect.Flags.Insert insert = android.hardware.audio.effect.Flags.Insert.ANY;
+  android.hardware.audio.effect.Flags.Volume volume = android.hardware.audio.effect.Flags.Volume.NONE;
+  android.hardware.audio.effect.Flags.HardwareAccelerator hwAcceleratorMode = android.hardware.audio.effect.Flags.HardwareAccelerator.NONE;
+  boolean offloadIndication;
+  boolean deviceIndication;
+  boolean audioModeIndication;
+  boolean audioSourceIndication;
+  boolean noProcessing;
+  @Backing(type="byte") @VintfStability
+  enum Type {
+    INSERT = 0,
+    AUXILIARY = 1,
+    REPLACE = 2,
+    PRE_PROC = 3,
+    POST_PROC = 4,
+  }
+  @Backing(type="byte") @VintfStability
+  enum Insert {
+    ANY = 0,
+    FIRST = 1,
+    LAST = 2,
+    EXCLUSIVE = 3,
+  }
+  @Backing(type="byte") @VintfStability
+  enum Volume {
+    NONE = 0,
+    CTRL = 1,
+    IND = 2,
+    MONITOR = 3,
+  }
+  @Backing(type="byte") @VintfStability
+  enum HardwareAccelerator {
+    NONE = 0,
+    SIMPLE = 1,
+    TUNNEL = 2,
+  }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl
new file mode 100644
index 0000000..e5c96f5
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+interface IEffect {
+  android.hardware.audio.effect.IEffect.OpenEffectReturn open(in android.hardware.audio.effect.Parameter.Common common, in android.hardware.audio.effect.Parameter.Specific specific);
+  void close();
+  android.hardware.audio.effect.Descriptor getDescriptor();
+  void command(in android.hardware.audio.effect.CommandId commandId);
+  android.hardware.audio.effect.State getState();
+  void setParameter(in android.hardware.audio.effect.Parameter param);
+  android.hardware.audio.effect.Parameter getParameter(in android.hardware.audio.effect.Parameter.Id paramId);
+  @FixedSize @VintfStability
+  parcelable Status {
+    int status;
+    int fmqByteConsumed;
+    int fmqByteProduced;
+  }
+  @VintfStability
+  parcelable OpenEffectReturn {
+    android.hardware.common.fmq.MQDescriptor<android.hardware.audio.effect.IEffect.Status,android.hardware.common.fmq.SynchronizedReadWrite> statusMQ;
+    android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> inputDataMQ;
+    android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> outputDataMQ;
+  }
+}
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
new file mode 100644
index 0000000..a22c591
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.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);
+  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
new file mode 100644
index 0000000..547112a
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union Parameter {
+  android.hardware.audio.effect.Parameter.Common common;
+  android.media.audio.common.AudioDeviceType device;
+  android.media.audio.common.AudioMode mode;
+  android.media.audio.common.AudioSource source;
+  android.hardware.audio.effect.Parameter.Volume volume;
+  boolean offload;
+  android.hardware.audio.effect.Parameter.VendorEffectParameter vendorEffect;
+  android.hardware.audio.effect.Parameter.Specific specific;
+  @VintfStability
+  union Id {
+    int commonTag;
+    int vendorTag;
+    android.hardware.audio.effect.Parameter.Specific.Id specificId;
+  }
+  @VintfStability
+  parcelable Common {
+    int session;
+    int ioHandle;
+    android.media.audio.common.AudioConfig input;
+    android.media.audio.common.AudioConfig output;
+  }
+  @VintfStability
+  parcelable Volume {
+    float left;
+    float right;
+  }
+  @VintfStability
+  parcelable VendorEffectParameter {
+    ParcelableHolder extension;
+  }
+  @VintfStability
+  union Specific {
+    android.hardware.audio.effect.Parameter.Specific.Id id;
+    android.hardware.audio.effect.Equalizer equalizer;
+    @VintfStability
+    union Id {
+      android.hardware.audio.effect.Equalizer.Tag equalizerTag = android.hardware.audio.effect.Equalizer.Tag.vendor;
+    }
+  }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl
new file mode 100644
index 0000000..a779ae4
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+parcelable Processing {
+  android.hardware.audio.effect.Processing.Type type;
+  android.hardware.audio.effect.Descriptor.Identity[] ids;
+  @VintfStability
+  union Type {
+    android.media.audio.common.AudioStreamType streamType = android.media.audio.common.AudioStreamType.INVALID;
+    android.media.audio.common.AudioSource source;
+  }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl
new file mode 100644
index 0000000..3176b01
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@Backing(type="byte") @VintfStability
+enum State {
+  INIT = 0,
+  IDLE = 1,
+  PROCESSING = 2,
+}
diff --git a/audio/aidl/android/hardware/audio/core/AudioPatch.aidl b/audio/aidl/android/hardware/audio/core/AudioPatch.aidl
new file mode 100644
index 0000000..005d4c0
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/AudioPatch.aidl
@@ -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.
+ */
+
+package android.hardware.audio.core;
+
+/**
+ * Audio patch specifies a connection between multiple audio port
+ * configurations.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable AudioPatch {
+    /** The ID of the patch, unique within the HAL module. */
+    int id;
+    /**
+     * The list of IDs of source audio port configs ('AudioPortConfig.id').
+     * There must be at least one source in a valid patch and all IDs must be
+     * unique.
+     */
+    int[] sourcePortConfigIds;
+    /**
+     * The list of IDs of sink audio port configs ('AudioPortConfig.id').
+     * There must be at least one sink in a valid patch and all IDs must be
+     * unique.
+     */
+    int[] sinkPortConfigIds;
+    /**
+     * The minimum buffer size, in frames, which streams must use for
+     * this connection configuration. This field is filled out by the
+     * HAL module on creation of the patch and must be a positive number.
+     */
+    int minimumStreamBufferSizeFrames;
+    /**
+     * Latencies, in milliseconds, associated with each sink port config from
+     * the 'sinkPortConfigIds' field. This field is filled out by the HAL module
+     * on creation or updating of the patch and must be a positive number. This
+     * is a nominal value. The current value of latency is provided via
+     * 'StreamDescriptor' command exchange on each audio I/O operation.
+     */
+    int[] latenciesMs;
+}
diff --git a/audio/aidl/android/hardware/audio/core/AudioRoute.aidl b/audio/aidl/android/hardware/audio/core/AudioRoute.aidl
new file mode 100644
index 0000000..1e7b441
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/AudioRoute.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.core;
+
+/**
+ * Audio route specifies a path from multiple audio source ports to one audio
+ * sink port. As an example, when emitting audio output, source ports typically
+ * are mix ports (audio data from the framework), the sink is a device
+ * port. When acquiring audio, source ports are device ports, the sink is a mix
+ * port.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable AudioRoute {
+    /**
+     * The list of IDs of source audio ports ('AudioPort.id').
+     * There must be at least one source in a valid route and all IDs must be
+     * unique.
+     */
+    int[] sourcePortIds;
+    /** The ID of the sink audio port ('AudioPort.id'). */
+    int sinkPortId;
+    /** If set, only one source can be active, mixing is not supported. */
+    boolean isExclusive;
+}
diff --git a/audio/aidl/android/hardware/audio/core/IConfig.aidl b/audio/aidl/android/hardware/audio/core/IConfig.aidl
new file mode 100644
index 0000000..c8ba6be
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/IConfig.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.audio.core;
+
+import android.hardware.audio.core.SurroundSoundConfig;
+
+/**
+ * This interface provides system-wide configuration parameters for audio I/O
+ * (by "system" here we mean the device running Android).
+ */
+@VintfStability
+interface IConfig {
+    /**
+     * Returns the surround sound configuration used for the Audio Policy
+     * Manager initial configuration.
+     *
+     * This method will only be called during the initialization of the Audio
+     * Policy Manager, and must always return the same result.
+     *
+     * @return The surround sound configuration
+     */
+    SurroundSoundConfig getSurroundSoundConfig();
+}
diff --git a/audio/aidl/android/hardware/audio/core/IModule.aidl b/audio/aidl/android/hardware/audio/core/IModule.aidl
new file mode 100644
index 0000000..735f87f
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/IModule.aidl
@@ -0,0 +1,484 @@
+/*
+ * 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.core;
+
+import android.hardware.audio.common.SinkMetadata;
+import android.hardware.audio.common.SourceMetadata;
+import android.hardware.audio.core.AudioPatch;
+import android.hardware.audio.core.AudioRoute;
+import android.hardware.audio.core.IStreamIn;
+import android.hardware.audio.core.IStreamOut;
+import android.hardware.audio.core.ModuleDebug;
+import android.hardware.audio.core.StreamDescriptor;
+import android.media.audio.common.AudioOffloadInfo;
+import android.media.audio.common.AudioPort;
+import android.media.audio.common.AudioPortConfig;
+
+/**
+ * Each instance of IModule corresponds to a separate audio module. The system
+ * (the term "system" as used here applies to the entire device running Android)
+ * may have multiple modules due to the physical architecture, for example, it
+ * can have multiple DSPs or other audio I/O units which are not interconnected
+ * in hardware directly. Usually there is at least one audio module which is
+ * responsible for the "main" (or "built-in") audio functionality of the
+ * system. Even if the system lacks any physical audio I/O capabilities, there
+ * will be a "null" audio module.
+ *
+ * On a typical mobile phone there is usually a main DSP module which handles
+ * most of the phone's audio I/O via the built-in speakers and microphones. USB
+ * audio can exist as a separate module. Some audio modules can be implemented
+ * purely in software, for example, the remote submix module.
+ */
+@VintfStability
+interface IModule {
+    /**
+     * Sets debugging configuration for the HAL module. This method is only
+     * called during xTS testing and is intended for validating the aspects of
+     * the HAL module behavior that would otherwise require human intervention.
+     *
+     * The HAL module must throw an error if there is an attempt to change
+     * the debug behavior for the aspect which is currently in use.
+     *
+     * @param debug The debug options.
+     * @throws EX_ILLEGAL_STATE If the flag(s) being changed affect functionality
+     *                          which is currently in use.
+     */
+    void setModuleDebug(in ModuleDebug debug);
+
+    /**
+     * Set a device port of an external device into connected state.
+     *
+     * This method is used to inform the HAL module that an external device has
+     * been connected to a device port selected using the 'id' field of the
+     * input AudioPort parameter. This device port must have dynamic profiles
+     * (an empty list of profiles). This port is further referenced to as "port
+     * template" because it acts as a template for creating a new instance of a
+     * "connected" device port which gets returned from this method.
+     *
+     * The input AudioPort parameter may contain any additional data obtained by
+     * the system side from other subsystems. The nature of data depends on the
+     * type of the connection. For example, for point-to-multipoint external
+     * device connections, the input parameter may contain the address of the
+     * connected external device. Another example is EDID information for HDMI
+     * connections (ExtraAudioDescriptor), which can be provided by the HDMI-CEC
+     * HAL module.
+     *
+     * It is the responsibility of the HAL module to query audio profiles
+     * supported by the connected device and return them as part of the returned
+     * AudioPort instance. In the case when the HAL is unable to query the
+     * external device, an error must be thrown.
+     *
+     * Thus, the returned audio port instance is the result of combining the
+     * following information:
+     *  - a unique port ID generated by the HAL module;
+     *  - static information from the port template;
+     *  - list of audio profiles supported by the connected device;
+     *  - additional data from the input AudioPort parameter.
+     *
+     * The HAL module must also update the list of audio routes to include the
+     * ID of the instantiated connected device port. Normally, the connected
+     * port allows the same routing as the port template.
+     *
+     * Also see notes on 'ModuleDebug.simulateDeviceConnections'.
+     *
+     * The following protocol is used by HAL module client for handling
+     * connection of an external device:
+     *  1. Obtain the list of device ports and their IDs via 'getAudioPorts'
+     *     method. Select the appropriate port template using
+     *     AudioDeviceDescription ('ext.device' field of AudioPort).
+     *  2. Combine the ID of the port template with any additional data and call
+     *     'connectExternalDevice'. The HAL module returns a new instance of
+     *     AudioPort created using the rules explained above. Both
+     *     'getAudioPort' and 'getAudioPorts' methods will be returning the same
+     *     information for this port until disconnection.
+     *  3. Configure the connected port with one of supported profiles using
+     *     'setAudioPortConfig'.
+     *  4. Query the list of AudioRoutes for the new AudioPort using
+     *     'getAudioRoutesForAudioPort' or 'getAudioRoutes' methods.
+     *
+     * External devices are distinguished by the connection type and device
+     * address. Calling this method multiple times to inform about connection of
+     * the same external device without disconnecting it first is an error.
+     *
+     * The HAL module must perform validation of the input parameter and throw
+     * an error if it is lacking required information, for example, when no
+     * device address is specified for a point-to-multipoint external device
+     * connection.
+     *
+     * Handling of a disconnect is done in a reverse order:
+     *  1. Reset port configuration using the 'resetAudioPortConfig' method.
+     *  2. Release the connected device port by calling the 'disconnectExternalDevice'
+     *     method. This also removes the audio routes associated with this
+     *     device port.
+     *
+     * @return New instance of an audio port for the connected external device.
+     * @param templateIdAndAdditionalData Specifies port template ID and any
+     *                                    additional data.
+     * @throws EX_ILLEGAL_ARGUMENT In the following cases:
+     *                             - If the template port can not be found by the ID.
+     *                             - If the template is not a device port, or
+     *                               it does not have dynamic profiles.
+     *                             - If the input parameter is lacking required
+     *                               information.
+     * @throws EX_ILLEGAL_STATE In the following cases:
+     *                          - If the HAL module is unable to query audio profiles.
+     *                          - If the external device has already been connected.
+     */
+    AudioPort connectExternalDevice(in AudioPort templateIdAndAdditionalData);
+
+    /**
+     * Set a device port of a an external device into disconnected state.
+     *
+     * This method is used to inform the HAL module that an external device has
+     * been disconnected. The 'portId' must be of a connected device port
+     * instance previously instantiated using the 'connectExternalDevice'
+     * method.
+     *
+     * @throws EX_ILLEGAL_ARGUMENT In the following cases:
+     *                             - If the port can not be found by the ID.
+     *                             - If this is not a connected device port.
+     * @throws EX_ILLEGAL_STATE If the port has active configurations.
+     */
+    void disconnectExternalDevice(int portId);
+
+    /**
+     * Return all audio patches of this module.
+     *
+     * Returns a list of audio patches, that is, established connections between
+     * audio port configurations.
+     *
+     * @return The list of audio patches.
+     */
+    AudioPatch[] getAudioPatches();
+
+    /**
+     * Return the current state of the audio port.
+     *
+     * Using the port ID provided on input, returns the current state of the
+     * audio port. The values of the AudioPort structure must be the same as
+     * currently returned by the 'getAudioPorts' method. The 'getAudioPort'
+     * method is provided to reduce overhead in the case when the client needs
+     * to check the state of one port only.
+     *
+     * @return The current state of an audio port.
+     * @param portId The ID of the audio port.
+     * @throws EX_ILLEGAL_ARGUMENT If the port can not be found by the ID.
+     */
+    AudioPort getAudioPort(int portId);
+
+    /**
+     * Return all active audio port configurations of this module.
+     *
+     * Returns a list of active configurations that are currently set for mix
+     * ports and device ports. Each returned configuration must have an unique
+     * ID within this module ('AudioPortConfig.id' field), which can coincide
+     * with an ID of an audio port, if the port only supports a single active
+     * configuration. Each returned configuration must also have a reference to
+     * an existing port ('AudioPortConfig.portId' field). All optional
+     * (nullable) fields of the configurations must be initialized by the HAL
+     * module.
+     *
+     * @return The list of active audio port configurations.
+     */
+    AudioPortConfig[] getAudioPortConfigs();
+
+    /**
+     * Return the current state of all audio ports provided by this module.
+     *
+     * Returns a list of all mix ports and device ports provided by this HAL
+     * module, reflecting their current states. Each returned port must have a
+     * unique ID within this module ('AudioPort.id' field). The list also
+     * includes "connected" ports created using 'connectExternalDevice' method.
+     *
+     * @return The list of audio ports.
+     */
+    AudioPort[] getAudioPorts();
+
+    /**
+     * Return all current audio routes of this module.
+     *
+     * Returns the current list of audio routes, that is, allowed connections
+     * between audio ports. The list can change when new device audio ports
+     * get created as a result of connecting or disconnecting of external
+     * devices.
+     *
+     * @return The list of audio routes.
+     */
+    AudioRoute[] getAudioRoutes();
+
+    /**
+     * Return audio routes related to the specified audio port.
+     *
+     * Returns the list of audio routes that include the specified port ID
+     * as a source or as a sink. The returned list is a subset of the result
+     * returned by the 'getAudioRoutes' method, filtered by the port ID.
+     * An empty list can be returned, indicating that the audio port can not
+     * be used for creating audio patches.
+     *
+     * @return The list of audio routes.
+     * @param portId The ID of the audio port.
+     * @throws EX_ILLEGAL_ARGUMENT If the port can not be found by the ID.
+     */
+    AudioRoute[] getAudioRoutesForAudioPort(int portId);
+
+    /**
+     * Open an input stream using an existing audio mix port configuration.
+     *
+     * The audio port configuration ID must be obtained by calling
+     * 'setAudioPortConfig' method. Existence of an audio patch involving this
+     * port configuration is not required for successful opening of a stream.
+     *
+     * The requested buffer size is expressed in frames, thus the actual size
+     * in bytes depends on the audio port configuration. Also, the HAL module
+     * may end up providing a larger buffer, thus the requested size is treated
+     * as the minimum size that the client needs. The minimum buffer size
+     * suggested by the HAL is in the 'AudioPatch.minimumStreamBufferSizeFrames'
+     * field, returned as a result of calling the 'setAudioPatch' method.
+     *
+     * Only one stream is allowed per audio port configuration. HAL module can
+     * also set a limit on how many output streams can be opened for a particular
+     * mix port by using its 'AudioPortMixExt.maxOpenStreamCount' field.
+     *
+     * Note that although it's not prohibited to open a stream on a mix port
+     * configuration which is not connected (using a patch) to any device port,
+     * and set up a patch afterwards, this sequence of calls is not recommended,
+     * because setting up of a patch might fail due to an insufficient stream
+     * buffer size. Another consequence of having a stream on an unconnected mix
+     * port is that capture positions can not be determined because there is no
+     * "external observer," thus read operations done via StreamDescriptor will
+     * be completing with an error, although data (zero filled) will still be
+     * provided.
+     *
+     * @return An opened input stream and the associated descriptor.
+     * @param args The pack of arguments, see 'OpenInputStreamArguments' parcelable.
+     * @throws EX_ILLEGAL_ARGUMENT In the following cases:
+     *                             - If the port config can not be found by the ID.
+     *                             - If the port config is not of an input mix port.
+     *                             - If a buffer of the requested size can not be provided.
+     * @throws EX_ILLEGAL_STATE In the following cases:
+     *                          - If the port config already has a stream opened on it.
+     *                          - If the limit on the open stream count for the port has
+     *                            been reached.
+     *                          - If the HAL module failed to initialize the stream.
+     */
+    @VintfStability
+    parcelable OpenInputStreamArguments {
+        /** The ID of the audio mix port config. */
+        int portConfigId;
+        /** Description of the audio that will be recorded. */
+        SinkMetadata sinkMetadata;
+        /** Requested audio I/O buffer minimum size, in frames. */
+        long bufferSizeFrames;
+    }
+    @VintfStability
+    parcelable OpenInputStreamReturn {
+        IStreamIn stream;
+        StreamDescriptor desc;
+    }
+    OpenInputStreamReturn openInputStream(in OpenInputStreamArguments args);
+
+    /**
+     * Open an output stream using an existing audio mix port configuration.
+     *
+     * The audio port configuration ID must be obtained by calling
+     * 'setAudioPortConfig' method. Existence of an audio patch involving this
+     * port configuration is not required for successful opening of a stream.
+     *
+     * If the port configuration has 'COMPRESS_OFFLOAD' output flag set,
+     * the framework must provide additional information about the encoded
+     * audio stream in 'offloadInfo' argument.
+     *
+     * The requested buffer size is expressed in frames, thus the actual size
+     * in bytes depends on the audio port configuration. Also, the HAL module
+     * may end up providing a larger buffer, thus the requested size is treated
+     * as the minimum size that the client needs. The minimum buffer size
+     * suggested by the HAL is in the 'AudioPatch.minimumStreamBufferSizeFrames'
+     * field, returned as a result of calling the 'setAudioPatch' method.
+     *
+     * Only one stream is allowed per audio port configuration. HAL module can
+     * also set a limit on how many output streams can be opened for a particular
+     * mix port by using its 'AudioPortMixExt.maxOpenStreamCount' field.
+     * Only one stream can be opened on the audio port with 'PRIMARY' output
+     * flag. This rule can not be overridden with 'maxOpenStreamCount' field.
+     *
+     * Note that although it's not prohibited to open a stream on a mix port
+     * configuration which is not connected (using a patch) to any device port,
+     * and set up a patch afterwards, this sequence of calls is not recommended,
+     * because setting up of a patch might fail due to an insufficient stream
+     * buffer size. Another consequence of having a stream on an unconnected mix
+     * port is that presentation positions can not be determined because there
+     * is no "external observer," thus write operations done via
+     * StreamDescriptor will be completing with an error, although the data
+     * will still be accepted and immediately discarded.
+     *
+     * @return An opened output stream and the associated descriptor.
+     * @param args The pack of arguments, see 'OpenOutputStreamArguments' parcelable.
+     * @throws EX_ILLEGAL_ARGUMENT In the following cases:
+     *                             - If the port config can not be found by the ID.
+     *                             - If the port config is not of an output mix port.
+     *                             - If the offload info is not provided for an offload
+     *                               port configuration.
+     *                             - If a buffer of the requested size can not be provided.
+     * @throws EX_ILLEGAL_STATE In the following cases:
+     *                          - If the port config already has a stream opened on it.
+     *                          - If the limit on the open stream count for the port has
+     *                            been reached.
+     *                          - If another opened stream already exists for the 'PRIMARY'
+     *                            output port.
+     *                          - If the HAL module failed to initialize the stream.
+     */
+    @VintfStability
+    parcelable OpenOutputStreamArguments {
+        /** The ID of the audio mix port config. */
+        int portConfigId;
+        /** Description of the audio that will be played. */
+        SourceMetadata sourceMetadata;
+        /** Additional information used for offloaded playback only. */
+        @nullable AudioOffloadInfo offloadInfo;
+        /** Requested audio I/O buffer minimum size, in frames. */
+        long bufferSizeFrames;
+    }
+    @VintfStability
+    parcelable OpenOutputStreamReturn {
+        IStreamOut stream;
+        StreamDescriptor desc;
+    }
+    OpenOutputStreamReturn openOutputStream(in OpenOutputStreamArguments args);
+
+    /**
+     * Set an audio patch.
+     *
+     * This method creates new or updates an existing audio patch. If the
+     * requested audio patch does not have a specified id, then a new patch is
+     * created and an ID is allocated for it by the HAL module. Otherwise an
+     * attempt to update an existing patch is made.
+     *
+     * The operation of updating an existing audio patch must not change
+     * playback state of audio streams opened on the audio port configurations
+     * of the patch. That is, the HAL module must still be able to consume or
+     * to provide data from / to streams continuously during the patch
+     * switching. Natural intermittent audible loss of some audio frames due to
+     * switching between device ports which does not affect stream playback is
+     * allowed. If the HAL module is unable to avoid playback or recording
+     * state change when updating a certain patch, it must return an error. In
+     * that case, the client must take care of changing port configurations,
+     * patches, and recreating streams in a way which provides an acceptable
+     * user experience.
+     *
+     * Audio port configurations specified in the patch must be obtained by
+     * calling 'setAudioPortConfig' method. There must be an audio route which
+     * allows connection between the audio ports whose configurations are used.
+     *
+     * When updating an existing audio patch, nominal latency values may change
+     * and must be provided by the HAL module in the returned 'AudioPatch'
+     * structure.
+     *
+     * @return Resulting audio patch.
+     * @param requested Requested audio patch.
+     * @throws EX_ILLEGAL_ARGUMENT In the following cases:
+     *                             - If the patch is invalid (see AudioPatch).
+     *                             - If a port config can not be found from the specified IDs.
+     *                             - If there are no routes satisfying the patch.
+     *                             - If an existing patch can not be found by the ID.
+     * @throws EX_ILLEGAL_STATE In the following cases:
+     *                          - If application of the patch can only use a route with an
+     *                            exclusive use the sink port, and it is already patched.
+     *                          - If updating an existing patch will cause interruption
+     *                            of audio, or requires re-opening of streams due to
+     *                            change of minimum audio I/O buffer size.
+     * @throws EX_UNSUPPORTED_OPERATION If the patch can not be established because
+     *                                  the HAL module does not support this otherwise valid
+     *                                  patch configuration. For example, if it's a patch
+     *                                  between multiple sources and sinks, and the HAL module
+     *                                  does not support this.
+     */
+    AudioPatch setAudioPatch(in AudioPatch requested);
+
+    /**
+     * Set the active configuration of an audio port.
+     *
+     * This method is used to create or update an active configuration for a mix
+     * port or a device port. The port is specified using the
+     * 'AudioPortConfig.portId' field. If the requested audio port
+     * configuration does not have a specified id in the 'AudioPortConfig.id'
+     * field, then a new configuration is created and an ID is allocated for it
+     * by the HAL module. Otherwise an attempt to update an existing port
+     * configuration is made. The HAL module returns the resulting audio port
+     * configuration. Depending on the port and on the capabilities of the HAL
+     * module, it can either update an existing port configuration (same port
+     * configuration ID remains), or create a new one. The resulting port
+     * configuration ID is returned in the 'id' field of the 'suggested'
+     * argument.
+     *
+     * If the specified port configuration can not be set, this method must
+     * return 'false' and provide its own suggestion in the output
+     * parameter. The framework can then set the suggested configuration on a
+     * subsequent retry call to this method.
+     *
+     * Device ports with dynamic audio profiles (an empty list of profiles)
+     * can not be used with this method. The list of profiles must be filled in
+     * as a result of calling 'connectExternalDevice' method.
+     *
+     * @return Whether the requested configuration has been applied.
+     * @param requested Requested audio port configuration.
+     * @param suggested Same as requested configuration, if it was applied.
+     *                  Suggested audio port configuration if the requested
+     *                  configuration can't be applied.
+     * @throws EX_ILLEGAL_ARGUMENT In the following cases:
+     *                             - If neither port config ID, nor port ID are specified.
+     *                             - If an existing port config can not be found by the ID.
+     *                             - If the port can not be found by the port ID.
+     *                             - If it is not possible to generate a suggested port
+     *                               configuration, for example, if the port only has dynamic
+     *                               profiles.
+     */
+    boolean setAudioPortConfig(in AudioPortConfig requested, out AudioPortConfig suggested);
+
+    /**
+     * Reset the audio patch.
+     *
+     * Resets previously created audio patch using its ID ('AudioPatch.id').  It
+     * is allowed to reset a patch which uses audio port configurations having
+     * associated streams. In this case the mix port becomes disconnected from
+     * the hardware, but the stream does not close.
+     *
+     * @param patchId The ID of the audio patch.
+     * @throws EX_ILLEGAL_ARGUMENT If an existing patch can not be found by the ID.
+     */
+    void resetAudioPatch(int patchId);
+
+    /**
+     * Reset the audio port configuration.
+     *
+     * Resets the specified audio port configuration, discarding all changes
+     * previously done by the framework. That means, if a call to this method is
+     * a success, the effect of all previous calls to 'setAudioPortConfig' which
+     * used or initially have generated the provided 'portConfigId', since the
+     * module start, or since the last call to this method, has been canceled.
+     *
+     * Audio port configurations of mix ports with streams opened on them can
+     * not be reset. Also can not be reset port configurations currently used by
+     * any patches.
+     *
+     * @param portConfigId The ID of the audio port config.
+     * @throws EX_ILLEGAL_ARGUMENT If the port config can not be found by the ID.
+     * @throws EX_ILLEGAL_STATE In the following cases:
+     *                          - If the port config has a stream opened on it;
+     *                          - If the port config is used by a patch.
+     */
+    void resetAudioPortConfig(int portConfigId);
+}
diff --git a/audio/aidl/android/hardware/audio/core/IStreamIn.aidl b/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
new file mode 100644
index 0000000..0c3e3d1
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
@@ -0,0 +1,50 @@
+/*
+ * 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.core;
+
+import android.hardware.audio.common.SinkMetadata;
+
+/**
+ * This interface provides means for receiving audio data from input devices.
+ */
+@VintfStability
+interface IStreamIn {
+    /**
+     * Close the stream.
+     *
+     * Releases any resources allocated for this stream on the HAL module side.
+     * This includes the fast message queues and shared memories returned via
+     * the StreamDescriptor. Thus, the stream can not be operated anymore after
+     * it has been closed. The client needs to release the audio data I/O
+     * objects after the call to this method returns.
+     *
+     * Methods of this interface throw EX_ILLEGAL_STATE for a closed stream.
+     *
+     * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+     */
+    void close();
+
+    /**
+     * Update stream metadata.
+     *
+     * Updates the metadata initially provided at the stream creation.
+     *
+     * @param sinkMetadata Updated metadata.
+     * @throws EX_ILLEGAL_STATE If the stream is closed.
+     */
+    void updateMetadata(in SinkMetadata sinkMetadata);
+}
diff --git a/audio/aidl/android/hardware/audio/core/IStreamOut.aidl b/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
new file mode 100644
index 0000000..9fdb37d
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
@@ -0,0 +1,50 @@
+/*
+ * 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.core;
+
+import android.hardware.audio.common.SourceMetadata;
+
+/**
+ * This interface provides means for sending audio data to output devices.
+ */
+@VintfStability
+interface IStreamOut {
+    /**
+     * Close the stream.
+     *
+     * Releases any resources allocated for this stream on the HAL module side.
+     * This includes the fast message queues and shared memories returned via
+     * the StreamDescriptor. Thus, the stream can not be operated anymore after
+     * it has been closed. The client needs to release the audio data I/O
+     * objects after the call to this method returns.
+     *
+     * Methods of this interface throw EX_ILLEGAL_STATE for a closed stream.
+     *
+     * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+     */
+    void close();
+
+    /**
+     * Update stream metadata.
+     *
+     * Updates the metadata initially provided at the stream creation.
+     *
+     * @param sourceMetadata Updated metadata.
+     * @throws EX_ILLEGAL_STATE If the stream is closed.
+     */
+    void updateMetadata(in SourceMetadata sourceMetadata);
+}
diff --git a/audio/aidl/android/hardware/audio/core/MmapBufferDescriptor.aidl b/audio/aidl/android/hardware/audio/core/MmapBufferDescriptor.aidl
new file mode 100644
index 0000000..108bcbe
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/MmapBufferDescriptor.aidl
@@ -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 android.hardware.audio.core;
+
+import android.hardware.common.Ashmem;
+
+/**
+ * MMap buffer descriptor is used by streams opened in MMap No IRQ mode.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable MmapBufferDescriptor {
+    /**
+     * MMap memory buffer.
+     */
+    Ashmem sharedMemory;
+    /**
+     * Transfer size granularity in frames.
+     */
+    long burstSizeFrames;
+    /**
+     * Attributes describing the buffer. Bitmask indexed by FLAG_INDEX_*
+     * constants.
+     */
+    int flags;
+
+    /**
+     * Whether the buffer can be securely shared to untrusted applications
+     * through the AAudio exclusive mode.
+     *
+     * Only set this flag if applications are restricted from accessing the
+     * memory surrounding the audio data buffer by a kernel mechanism.
+     * See Linux kernel's dma-buf
+     * (https://www.kernel.org/doc/html/v4.16/driver-api/dma-buf.html).
+     */
+    const int FLAG_INDEX_APPLICATION_SHAREABLE = 0;
+}
diff --git a/audio/aidl/android/hardware/audio/core/ModuleDebug.aidl b/audio/aidl/android/hardware/audio/core/ModuleDebug.aidl
new file mode 100644
index 0000000..858a9bd
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/ModuleDebug.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.core;
+
+/**
+ * This structure contains flags used for enabling various debugging aspects
+ * in a HAL module. By default, all debugging aspects are turned off. They
+ * can be enabled during xTS tests for functionality that, for example, would
+ * otherwise require human intervention (e.g. connection of external devices).
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable ModuleDebug {
+    /**
+     * When set to 'true', HAL module must simulate connection of external
+     * devices. An external device becomes 'connected' after a call to
+     * IModule.connectExternalDevice, simulation of connection requires:
+     *  - provision of at least one non-dynamic device port profile on
+     *    connection (as if it was retrieved from a connected device);
+     *  - simulating successful application of port configurations for reported
+     *    profiles.
+     */
+    boolean simulateDeviceConnections;
+}
diff --git a/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl b/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
new file mode 100644
index 0000000..2b1ed8c
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
@@ -0,0 +1,213 @@
+/*
+ * 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.core;
+
+import android.hardware.audio.core.MmapBufferDescriptor;
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+
+/**
+ * Stream descriptor contains fast message queues and buffers used for sending
+ * and receiving audio data. The descriptor complements IStream* interfaces by
+ * providing communication channels that serve as an alternative to Binder
+ * transactions.
+ *
+ * Handling of audio data and commands must be done by the HAL module on a
+ * dedicated thread with high priority, for all modes, including MMap No
+ * IRQ. The HAL module is responsible for creating this thread and setting its
+ * priority. The HAL module is also responsible for serializing access to the
+ * internal components of the stream while serving commands invoked via the
+ * stream's AIDL interface and commands invoked via the command queue of the
+ * descriptor.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable StreamDescriptor {
+    /**
+     * Position binds together a position within the stream and time.
+     *
+     * The timestamp must use "monotonic" clock.
+     *
+     * The frame count must advance between consecutive I/O operations, and stop
+     * advancing when the stream was put into the 'standby' mode. On exiting the
+     * 'standby' mode, the frame count must not reset, but continue counting.
+     */
+    @VintfStability
+    @FixedSize
+    parcelable Position {
+        /** Frame count. */
+        long frames;
+        /** Timestamp in nanoseconds. */
+        long timeNs;
+    }
+
+    /**
+     * The command used for audio I/O, see 'AudioBuffer'. For MMap No IRQ mode
+     * this command only provides updated positions and latency because actual
+     * audio I/O is done via the 'AudioBuffer.mmap' shared buffer.
+     */
+    const int COMMAND_BURST = 1;
+
+    /**
+     * Used for sending commands to the HAL module. The client writes into
+     * the queue, the HAL module reads. The queue can only contain a single
+     * command.
+     */
+    @VintfStability
+    @FixedSize
+    parcelable Command {
+        /**
+         * One of COMMAND_* codes.
+         */
+        int code;
+        /**
+         * For output streams: the amount of bytes that the client requests the
+         *   HAL module to read from the 'audio.fmq' queue.
+         * For input streams: the amount of bytes requested by the client to
+         *   read from the hardware into the 'audio.fmq' queue.
+         *
+         * In both cases it is allowed for this field to contain any
+         * non-negative number. The value 0 can be used if the client only needs
+         * to retrieve current positions and latency. Any sufficiently big value
+         * which exceeds the size of the queue's area which is currently
+         * available for reading or writing by the HAL module must be trimmed by
+         * the HAL module to the available size. Note that the HAL module is
+         * allowed to consume or provide less data than requested, and it must
+         * return the amount of actually read or written data via the
+         * 'Reply.fmqByteCount' field. Thus, only attempts to pass a negative
+         * number must be constituted as a client's error.
+         */
+        int fmqByteCount;
+    }
+    MQDescriptor<Command, SynchronizedReadWrite> command;
+
+    /**
+     * Used for providing replies to commands. The HAL module writes into
+     * the queue, the client reads. The queue can only contain a single reply,
+     * corresponding to the last command sent by the client.
+     */
+    @VintfStability
+    @FixedSize
+    parcelable Reply {
+        /**
+         * One of Binder STATUS_* statuses:
+         *  - STATUS_OK: the command has completed successfully;
+         *  - STATUS_BAD_VALUE: invalid value in the 'Command' structure;
+         *  - STATUS_INVALID_OPERATION: the mix port is not connected
+         *                              to any producer or consumer, thus
+         *                              positions can not be reported;
+         *  - STATUS_NOT_ENOUGH_DATA: a read or write error has
+         *                            occurred for the 'audio.fmq' queue;
+         *
+         */
+        int status;
+        /**
+         * For output streams: the amount of bytes actually consumed by the HAL
+         *   module from the 'audio.fmq' queue.
+         * For input streams: the amount of bytes actually provided by the HAL
+         *   in the 'audio.fmq' queue.
+         *
+         * The returned value must not exceed the value passed in the
+         * 'fmqByteCount' field of the corresponding command or be negative.
+         */
+        int fmqByteCount;
+        /**
+         * For output streams: the moment when the specified stream position
+         *   was presented to an external observer (i.e. presentation position).
+         * For input streams: the moment when data at the specified stream position
+         *   was acquired (i.e. capture position).
+         */
+        Position observable;
+        /**
+         * Used only for MMap streams to provide the hardware read / write
+         * position for audio data in the shared memory buffer 'audio.mmap'.
+         */
+        Position hardware;
+        /**
+         * Current latency reported by the hardware.
+         */
+        int latencyMs;
+    }
+    MQDescriptor<Reply, SynchronizedReadWrite> reply;
+
+    /**
+     * The size of one frame of audio data in bytes. For PCM formats this is
+     * usually equal to the size of a sample multiplied by the number of
+     * channels used. For encoded bitstreams encapsulated into PCM the sample
+     * size of the underlying PCM stream is used. For encoded bitstreams that
+     * are passed without encapsulation, the frame size is usually 1 byte.
+     */
+    int frameSizeBytes;
+    /**
+     * Total buffer size in frames. This applies both to the size of the 'audio.fmq'
+     * queue and to the size of the shared memory buffer for MMap No IRQ streams.
+     * Note that this size may end up being slightly larger than the size requested
+     * in a call to 'IModule.openInputStream' or 'openOutputStream' due to memory
+     * alignment requirements.
+     */
+    long bufferSizeFrames;
+
+    /**
+     * Used for sending or receiving audio data to/from the stream. In the case
+     * of MMap No IRQ streams this structure only contains the information about
+     * the shared memory buffer. Audio data is sent via the shared buffer
+     * directly.
+     */
+    @VintfStability
+    union AudioBuffer {
+        /**
+         * The fast message queue used for all modes except MMap No IRQ.  Both
+         * reads and writes into this queue are non-blocking because access to
+         * this queue is synchronized via the 'command' and 'reply' queues as
+         * described below. The queue nevertheless uses 'SynchronizedReadWrite'
+         * because there is only one reader, and the reading position must be
+         * shared.
+         *
+         * For output streams the following sequence of operations is used:
+         *  1. The client writes audio data into the 'audio.fmq' queue.
+         *  2. The client writes the 'BURST' command into the 'command' queue,
+         *     and hangs on waiting on a read from the 'reply' queue.
+         *  3. The high priority thread in the HAL module wakes up due to 2.
+         *  4. The HAL module reads the command and audio data.
+         *  5. The HAL module writes the command status and current positions
+         *     into 'reply' queue, and hangs on waiting on a read from
+         *     the 'command' queue.
+         *  6. The client wakes up due to 5. and reads the reply.
+         *
+         * For input streams the following sequence of operations is used:
+         *  1. The client writes the 'BURST' command into the 'command' queue,
+         *     and hangs on waiting on a read from the 'reply' queue.
+         *  2. The high priority thread in the HAL module wakes up due to 1.
+         *  3. The HAL module writes audio data into the 'audio.fmq' queue.
+         *  4. The HAL module writes the command status and current positions
+         *     into 'reply' queue, and hangs on waiting on a read from
+         *     the 'command' queue.
+         *  5. The client wakes up due to 4.
+         *  6. The client reads the reply and audio data.
+         */
+        MQDescriptor<byte, SynchronizedReadWrite> fmq;
+        /**
+         * MMap buffers are shared directly with the DSP, which operates
+         * independently from the CPU. Writes and reads into these buffers
+         * are not synchronized with 'command' and 'reply' queues. However,
+         * the client still uses the 'BURST' command for obtaining current
+         * positions from the HAL module.
+         */
+        MmapBufferDescriptor mmap;
+    }
+    AudioBuffer audio;
+}
diff --git a/audio/aidl/android/hardware/audio/core/SurroundSoundConfig.aidl b/audio/aidl/android/hardware/audio/core/SurroundSoundConfig.aidl
new file mode 100644
index 0000000..eeda12a
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/SurroundSoundConfig.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.core;
+
+import android.media.audio.common.AudioFormatDescription;
+
+/**
+ * SurroundSoundConfig defines the multi-channel formats that can be enabled on
+ * (primarily TV) devices.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable SurroundSoundConfig {
+    @VintfStability
+    parcelable SurroundFormatFamily {
+        /**
+         * A primaryFormat shall get an entry in the Surround Settings dialog on TV
+         * devices. There must be a corresponding Java ENCODING_... constant
+         * defined in AudioFormat.java, and a display name defined in
+         * AudioFormat.toDisplayName.
+         */
+        AudioFormatDescription primaryFormat;
+        /**
+         * List of formats that shall be equivalent to the primaryFormat from the
+         * users' point of view and don't need a dedicated Surround Settings
+         * dialog entry.
+         */
+        AudioFormatDescription[] subFormats;
+    }
+    SurroundFormatFamily[] formatFamilies;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Capability.aidl b/audio/aidl/android/hardware/audio/effect/Capability.aidl
new file mode 100644
index 0000000..e792f86
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Capability.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.Equalizer;
+
+/**
+ * Effect capability definitions.
+ * This data structure is used as part of effect Descriptor to identify effect capabilities which
+ * not meant to change at runtime.
+ */
+@VintfStability
+union Capability {
+    /**
+     * Vendor defined effect capability.
+     * This extension can be used when vendor have a new effect implementated and need
+     * capability definition for this new type of effect.
+     * If vendor want to extend existing effect capabilities, it is recommended to expose though
+     * the ParcelableHolder in each effect capability definition. For example:
+     * Equalizer.Capability.extension.
+     */
+    @VintfStability
+    parcelable VendorEffectCapability {
+        ParcelableHolder extension;
+    }
+    VendorEffectCapability vendor;
+
+    /**
+     * Equalizer capability definition.
+     */
+    Equalizer.Capability equalizer;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/CommandId.aidl b/audio/aidl/android/hardware/audio/effect/CommandId.aidl
new file mode 100644
index 0000000..d940b42
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/CommandId.aidl
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+/**
+ * Defines all commands supported by the effect instance.
+ *
+ * There are three groups of commands:
+ * 1. Common part which MUST be supported by all effects.
+ * 2. Commands MUST be supported by a specific type of effect.
+ * 3. Extension commands for vendor.
+ */
+@VintfStability
+@Backing(type="int")
+enum CommandId {
+    /**
+     * Commands MUST be supported by all effects.
+     */
+    /**
+     * Start effect engine processing.
+     * An effect instance must start processing data and transfer to PROCESSING state if it is in
+     * IDLE state and have all necessary information. Otherwise it must:
+     * 1. Throw a EX_ILLEGAL_STATE exception if effect is not in IDLE state, or
+     * 2. Throw a EX_TRANSACTION_FAILED for all other errors.
+     *
+     * Depending on parameters set to the effect instance, effect may do process or reverse
+     * process after START command.
+     */
+    START = 0,
+    /**
+     * Stop effect engine processing with all resource kept.
+     * The currently processed audio data will be discarded if the effect engine is in PROCESSING
+     * state.
+     * Effect instance must do nothing and return ok when it receive STOP command in IDLE state.
+     */
+    STOP = 1,
+    /**
+     * Keep all parameter settings but reset the buffer content, stop engine processing, and transit
+     * instance state to IDLE if its in PROCESSING state.
+     * Effect instance must be able to handle RESET command at IDLE and PROCESSING states.
+     */
+    RESET = 2,
+
+    /**
+     * Commands MUST be supported by a specific type of effect.
+     */
+
+    /**
+     * Extension commands for vendor.
+     */
+    VENDOR_COMMAND_0 = 0x100,
+    VENDOR_COMMAND_1,
+    VENDOR_COMMAND_2,
+    VENDOR_COMMAND_3,
+    VENDOR_COMMAND_4,
+    VENDOR_COMMAND_5,
+    VENDOR_COMMAND_6,
+    VENDOR_COMMAND_7,
+    VENDOR_COMMAND_8,
+    VENDOR_COMMAND_9,
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
new file mode 100644
index 0000000..562c249
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
@@ -0,0 +1,149 @@
+/*
+ * 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.Capability;
+import android.hardware.audio.effect.Flags;
+import android.media.audio.common.AudioUuid;
+
+/**
+ * Descriptor contains all information (capabilities, attributes, etc) for an effect implementation.
+ * The client uses this information to decide when and how to apply an effect implementation.
+ *
+ * Each type of effect can have more than one implementation (differentiated by implementation
+ * UUID), the effect proxy act as a combination of two implementations (usually one software and
+ * one offload implementation), so effect processing can be seamlessly switched between
+ * implementations in same proxy depending on the configuration and/or use case. If the optional
+ * proxy UUID is specified in Descriptor.Identity, then client must consider the effect instance as
+ * part of the effect proxy.
+ */
+@VintfStability
+parcelable Descriptor {
+    /**
+     * UUID for effect types, these definitions are in sync with SDK, see @c AudioEffect.java.
+     */
+    /**
+     * UUID for environmental reverberation effect type.
+     */
+    const String EFFECT_TYPE_UUID_ENV_REVERB = "c2e5d5f0-94bd-4763-9cac-4e234d06839e";
+    /**
+     * UUID for preset reverberation effect type.
+     */
+    const String EFFECT_TYPE_UUID_PRESET_REVERB = "47382d60-ddd8-11db-bf3a-0002a5d5c51b";
+    /**
+     * UUID for equalizer effect type.
+     */
+    const String EFFECT_TYPE_UUID_EQUALIZER = "0bed4300-ddd6-11db-8f34-0002a5d5c51b";
+    /**
+     * UUID for bass boost effect type.
+     */
+    const String EFFECT_TYPE_UUID_BASS_BOOST = "0634f220-ddd4-11db-a0fc-0002a5d5c51b";
+    /**
+     * UUID for virtualizer effect type.
+     */
+    const String EFFECT_TYPE_UUID_VIRTUALIZER = "37cc2c00-dddd-11db-8577-0002a5d5c51b";
+    /**
+     * UUID for Automatic Gain Control (AGC) type.
+     */
+    const String EFFECT_TYPE_UUID_AGC = "0a8abfe0-654c-11e0-ba26-0002a5d5c51b";
+    /**
+     * UUID for Acoustic Echo Canceler (AEC) type.
+     */
+    const String EFFECT_TYPE_UUID_AEC = "7b491460-8d4d-11e0-bd61-0002a5d5c51b";
+    /**
+     * UUID for Noise Suppressor (NS) type.
+     */
+    const String EFFECT_TYPE_UUID_NS = "58b4b260-8e06-11e0-aa8e-0002a5d5c51b";
+    /**
+     * UUID for Loudness Enhancer type.
+     */
+    const String EFFECT_TYPE_UUID_LOUDNESS_ENHANCER = "fe3199be-aed0-413f-87bb-11260eb63cf1";
+    /**
+     * UUID for Dynamics Processing type.
+     */
+    const String EFFECT_TYPE_UUID_DYNAMICS_PROCESSING = "7261676f-6d75-7369-6364-28e2fd3ac39e";
+    /**
+     * UUID for Haptic Generator type.
+     */
+    const String EFFECT_TYPE_UUID_HAPTIC_GENERATOR = "1411e6d6-aecd-4021-a1cf-a6aceb0d71e5";
+    /**
+     * UUID for Spatializer type.
+     */
+    const String EFFECT_TYPE_UUID_SPATIALIZER = "ccd4cf09-a79d-46c2-9aae-06a1698d6c8f";
+    /**
+     * UUID for Volume type. The volume effect is used for automated tests only.
+     */
+    const String EFFECT_TYPE_UUID_VOLUME = "09e8ede0-ddde-11db-b4f6-0002a5d5c51b";
+
+    /**
+     * This structure completely identifies an effect implementation.
+     */
+    @VintfStability
+    parcelable Identity {
+        /**
+         * UUID for the type of effect.
+         */
+        AudioUuid type;
+        /**
+         * UUID for this particular implementation.
+         */
+        AudioUuid uuid;
+        /**
+         * Optional proxy UUID. This field must be set to the proxy effect type UUID if the effect
+         * implementation is part of a proxy effect.
+         */
+        @nullable AudioUuid proxy;
+        /**
+         * Capability flags defined for the effect implementation.
+         */
+        Flags flags;
+    }
+
+    /**
+     * Common attributes of all effect implementation.
+     */
+    @VintfStability
+    parcelable Common {
+        /**
+         * Identity of effect implementation.
+         */
+        Identity id;
+        /**
+         * CPU load indication expressed in 0.1 MIPS units as estimated on an ARM9E core (ARMv5TE)
+         * with 0 WS.
+         */
+        int cpuLoad;
+        /**
+         * Data memory usage expressed in KB and includes only dynamically allocated memory.
+         */
+        int memoryUsage;
+        /**
+         * Human readable effect name, no intended to display on UI directly.
+         */
+        @utf8InCpp String name;
+        /**
+         * Human readable effect implementor name, no intended to display on UI directly.
+         */
+        @utf8InCpp String implementor;
+    }
+    Common common;
+
+    /**
+     * Effect implementation capability.
+     */
+    Capability capability;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Equalizer.aidl b/audio/aidl/android/hardware/audio/effect/Equalizer.aidl
new file mode 100644
index 0000000..7fe9bb2
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Equalizer.aidl
@@ -0,0 +1,99 @@
+/*
+ * 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.media.audio.common.AudioProfile;
+
+/**
+ * Equalizer specific definitions.
+ *
+ * All parameters defined in union Equalizer must be gettable and settable. The capabilities defined
+ * in Equalizer.Capability can only acquired with IEffect.getDescriptor() and not settable.
+ */
+@VintfStability
+union Equalizer {
+    /**
+     * Vendor Equalizer implementation definition for additional parameters.
+     */
+    @VintfStability
+    parcelable VendorExtension {
+        ParcelableHolder extension;
+    }
+    VendorExtension vendor;
+
+    /**
+     * Capability MUST be supported by Equalizer implementation.
+     */
+    @VintfStability
+    parcelable Capability {
+        /**
+         * Equalizer capability extension, vendor can use this extension in case existing capability
+         * definition not enough.
+         */
+        ParcelableHolder extension;
+
+        /**
+         * Bands frequency ranges supported.
+         */
+        BandFrequency[] bandFrequencies;
+
+        /**
+         * Presets name and index.
+         */
+        Preset[] presets;
+    }
+
+    /**
+     * Level setting for each band.
+     */
+    @VintfStability
+    parcelable BandLevel {
+        int index;
+        int level;
+    }
+
+    /**
+     * Supported minimal and maximal frequency for each band.
+     */
+    @VintfStability
+    parcelable BandFrequency {
+        int index;
+        int min;
+        int max;
+    }
+
+    /**
+     * Factory presets supported.
+     */
+    @VintfStability
+    parcelable Preset {
+        int index;
+        /**
+         * Preset name, used to identify presets but no intended to display on UI directly.
+         */
+        @utf8InCpp String name;
+    }
+
+    /**
+     * Level for each band.
+     */
+    BandLevel[] bandLevels;
+    /**
+     * Index of current preset.
+     */
+    int preset;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Flags.aidl b/audio/aidl/android/hardware/audio/effect/Flags.aidl
new file mode 100644
index 0000000..f449c2d
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Flags.aidl
@@ -0,0 +1,147 @@
+/*
+ * 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;
+
+/**
+ * Some common capability for an effect instance.
+ */
+@VintfStability
+parcelable Flags {
+    /**
+     * Type of connection.
+     */
+    @VintfStability
+    @Backing(type="byte")
+    enum Type {
+        /**
+         * After track process.
+         */
+        INSERT = 0,
+        /**
+         * Connect to track auxiliary output and use send level.
+         */
+        AUXILIARY = 1,
+        /**
+         * Rreplaces track process function; must implement SRC, volume and mono to stereo.
+         */
+        REPLACE = 2,
+        /**
+         * Applied below audio HAL on in.
+         */
+        PRE_PROC = 3,
+        /**
+         * Applied below audio HAL on out.
+         */
+        POST_PROC = 4,
+    }
+    Type type = Type.INSERT;
+
+    /**
+     * Insertion preference.
+     */
+    @VintfStability
+    @Backing(type="byte")
+    enum Insert {
+        ANY = 0,
+        /**
+         * First of the chain.
+         */
+        FIRST = 1,
+        /**
+         * Last of the chain.
+         */
+        LAST = 2,
+        /**
+         * Exclusive (only effect in the insert chain.
+         */
+        EXCLUSIVE = 3,
+    }
+    Insert insert = Insert.ANY;
+
+    @VintfStability
+    @Backing(type="byte")
+    enum Volume {
+        NONE = 0,
+        /**
+         * Implements volume control.
+         */
+        CTRL = 1,
+        /**
+         * Requires volume indication.
+         */
+        IND = 2,
+        /**
+         * Monitors requested volume.
+         */
+        MONITOR = 3,
+    }
+    Volume volume = Volume.NONE;
+
+    @VintfStability
+    @Backing(type="byte")
+    enum HardwareAccelerator {
+        /**
+         * No hardware acceleration
+         */
+        NONE = 0,
+        /**
+         * Non tunneled hw acceleration: effect reads the samples, send them to HW accelerated
+         * effect processor, reads back the processed samples and returns them to the output buffer.
+         */
+        SIMPLE = 1,
+        /**
+         * The effect interface is only used to control the effect engine. This mode is relevant for
+         * global effects actually applied by the audio hardware on the output stream.
+         */
+        TUNNEL = 2,
+    }
+    HardwareAccelerator hwAcceleratorMode = HardwareAccelerator.NONE;
+
+    /**
+     * Effect instance set this flag to true if it requires update on if the playback thread the
+     * effect attached to is offloaded or not. In this case the framework must call
+     * IEffect.setParameter(Parameter.offload) to notify effect instance when playback thread
+     * offload changes.
+     */
+    boolean offloadIndication;
+
+    /**
+     * Effect instance set this flag to true if it requires device change update. In this case the
+     * framework must call IEffect.setParameter(Parameter.device) to notify effect instance when the
+     * device changes.
+     */
+    boolean deviceIndication;
+
+    /**
+     * Effect instance set this flag to true if it requires audio mode change update. In this case
+     * the framework must call IEffect.setParameter(Parameter.mode) to notify effect instance when
+     * the audio mode changes.
+     */
+    boolean audioModeIndication;
+
+    /**
+     * Effect instance set this flag to true if it requires audio source change update. In this case
+     * the framework must call IEffect.setParameter(Parameter.source) to notify effect instance when
+     * the audio source changes.
+     */
+    boolean audioSourceIndication;
+
+    /**
+     * Set to true if no processing done for this effect instance.
+     */
+    boolean noProcessing;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/IEffect.aidl b/audio/aidl/android/hardware/audio/effect/IEffect.aidl
new file mode 100644
index 0000000..5dd390f
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/IEffect.aidl
@@ -0,0 +1,166 @@
+/*
+ * 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.CommandId;
+import android.hardware.audio.effect.Descriptor;
+import android.hardware.audio.effect.Parameter;
+import android.hardware.audio.effect.State;
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+
+/**
+ * Effect interfaces definitions to configure and control the effect instance.
+ */
+@VintfStability
+interface IEffect {
+    @VintfStability
+    @FixedSize
+    parcelable Status {
+        /**
+         * One of Binder STATUS_* statuses:
+         *  - STATUS_OK: the command has completed successfully;
+         *  - STATUS_BAD_VALUE: invalid value in the 'Command' structure;
+         *  - STATUS_INVALID_OPERATION: the mix port is not connected
+         *                              to any producer or consumer, thus
+         *                              positions can not be reported;
+         *  - STATUS_NOT_ENOUGH_DATA: a read or write error has
+         *                            occurred for the 'audio.fmq' queue;
+         *
+         */
+        int status;
+        /**
+         * The amount of bytes consumed by the effect instance.
+         */
+        int fmqByteConsumed;
+        /**
+         * The amount of bytes produced by the effect instance.
+         */
+        int fmqByteProduced;
+    }
+
+    /**
+     * Return data structure of IEffect.open() interface.
+     */
+    @VintfStability
+    parcelable OpenEffectReturn {
+        /**
+         * Message queue for effect processing status.
+         */
+        MQDescriptor<Status, SynchronizedReadWrite> statusMQ;
+        /**
+         * Message queue for input data buffer.
+         */
+        MQDescriptor<byte, SynchronizedReadWrite> inputDataMQ;
+        /**
+         * Message queue for output data buffer.
+         */
+        MQDescriptor<byte, SynchronizedReadWrite> outputDataMQ;
+    }
+
+    /**
+     * Open an effect instance, effect must not start processing data before receive
+     * CommandId::START command. All necessary information should be allocated and instance must
+     * transfer to State::IDLE state after open() call has been handled successfully. After open,
+     * the effect instance must be able to handle all IEffect interface calls.
+     *
+     * @param common Parameters which MUST pass from client at open time.
+     *
+     * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported command.
+     * @throws a EX_UNSUPPORTED_OPERATION if device capability/resource is not enough or system
+     *         failure happens.
+     * @note Open an already-opened effect instance should do nothing and should not throw an error.
+     */
+    OpenEffectReturn open(in Parameter.Common common, in Parameter.Specific specific);
+
+    /**
+     * Called by the client to close the effect instance, processing thread should be destroyed and
+     * consume no CPU after close.
+     *
+     * It is recommended to close the effect on the client side as soon as it becomes unused, it's
+     * client responsibility to make sure all parameter/buffer is correct if client wants to reopen
+     * a closed instance.
+     *
+     * Effect instance close interface should always succeed unless:
+     * 1. The effect instance is not in a proper state to be closed, for example it's still in
+     * State::PROCESSING state.
+     * 2. There is system/hardware related failure when close.
+     *
+     * @throws EX_ILLEGAL_STATE if the effect instance is not in a proper state to be closed.
+     * @throws EX_UNSUPPORTED_OPERATION if the effect instance failed to close for any other reason.
+     * @note Close an already-closed effect should do nothing and should not throw an error.
+     */
+    void close();
+
+    /**
+     * Return the @c Descriptor of this effect instance.
+     *
+     * Must be available for the effect instance at anytime and should always succeed.
+     *
+     * @return Descriptor The @c Descriptor of this effect instance.
+     */
+    Descriptor getDescriptor();
+
+    /**
+     * Send a command (defined in enum CommandId) to the effect instance, instance state can be
+     * changed as result of command handling.
+     *
+     * Must be available for the effect instance after it has been open().
+     *
+     * @param commandId ID of the command send to the effect instance.
+     *
+     * @throws EX_ILLEGAL_STATE if the effect instance is not in a proper state to handle the
+     * command.
+     * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported command.
+     */
+    void command(in CommandId commandId);
+
+    /**
+     * Get current state of the effect instance.
+     *
+     * Must be available for the effect instance at anytime and should always succeed.
+     *
+     * @return Current effect instance state.
+     */
+    State getState();
+
+    /**
+     * Set a parameter to the effect instance.
+     *
+     * Must be available for the effect instance after open().
+     *
+     * @param param Parameter data to set to the effect instance.
+     *
+     * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported parameter.
+     */
+    void setParameter(in Parameter param);
+
+    /**
+     * Get a parameter from the effect instance with parameter ID.
+     *
+     * This interface must return the current parameter of the effect instance, if no parameter
+     * has been set by client yet, the default value must be returned.
+     *
+     * Must be available for the effect instance after open().
+     *
+     * @param paramId The tag enum of parameter to get.
+     * @return Parameter The parameter to get from the effect instance.
+     *
+     * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported parameter tag.
+     */
+    Parameter getParameter(in Parameter.Id paramId);
+}
diff --git a/audio/aidl/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
new file mode 100644
index 0000000..e56c24f
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
@@ -0,0 +1,83 @@
+/*
+ * 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.Descriptor;
+import android.hardware.audio.effect.IEffect;
+import android.hardware.audio.effect.Processing;
+import android.media.audio.common.AudioUuid;
+
+/**
+ * Provides system-wide effect factory interfaces.
+ *
+ * An android.hardware.audio.effect.IFactory platform service is registered with ServiceManager, and
+ * is always available on the device.
+ *
+ */
+@VintfStability
+interface IFactory {
+    /**
+     * Return a list of effect identities 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
+     *        null, used as a filter for effect type UUIDs.
+     * @param implementation Indicates the particular implementation of the effect in that type.
+     *        This is an optional parameter, pass in null if this parameter is not necessary; if
+     *        non null, used as a filter for effect type UUIDs.
+     * @return List of effect identities supported and filtered by type/implementation UUID.
+     */
+    Descriptor.Identity[] queryEffects(
+            in @nullable AudioUuid type, in @nullable AudioUuid implementation);
+
+    /**
+     * Return a list of defined processings, with the optional filter by Processing type.
+     * An effect can exist more than once in the returned list, which means this effect must be used
+     * in more than one processing type.
+     *
+     * @param type Type of processing to query, can be AudioStreamType, AudioSource, or null.
+     * @return list of processing defined with the optional filter by Processing.Type.
+     */
+    Processing[] queryProcessing(in @nullable Processing.Type type);
+
+    /**
+     * Called by the audio framework to create the effect (identified by the implementation UUID
+     * parameter).
+     *
+     * The effect instance should be able to maintain its own context and parameters after creation.
+     *
+     * @param implUuid UUID for the effect implementation which instance will be created based on.
+     * @return The effect instance handle created.
+     * @throws EX_ILLEGAL_ARGUMENT if the implUuid is not valid.
+     * @throws EX_TRANSACTION_FAILED if device capability/resource is not enough to create the
+     *         effect instance.
+     */
+    IEffect createEffect(in AudioUuid implUuid);
+
+    /**
+     * Called by the framework to destroy the effect and free up all currently allocated resources.
+     * It is recommended to destroy the effect from the client side as soon as it is becomes unused.
+     *
+     * The client must ensure effect instance is closed before destroy.
+     *
+     * @param handle The handle of effect instance to be destroyed.
+     * @throws EX_ILLEGAL_ARGUMENT if the effect handle is not valid.
+     * @throws EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+     */
+    void destroyEffect(in IEffect handle);
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/android/hardware/audio/effect/Parameter.aidl
new file mode 100644
index 0000000..739c9ff
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Parameter.aidl
@@ -0,0 +1,146 @@
+/*
+ * 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.Equalizer;
+import android.media.audio.common.AudioConfig;
+import android.media.audio.common.AudioDeviceType;
+import android.media.audio.common.AudioMode;
+import android.media.audio.common.AudioSource;
+
+/**
+ * Defines all parameters supported by the effect instance.
+ *
+ * There are three groups of parameters:
+ * 1. Common parameters are essential parameters, MUST pass to effects at open() interface.
+ * 2. Parameters defined for a specific effect type.
+ * 3. Extension parameters for vendor.
+ *
+ * For all supported parameter, implementation MUST support both set and get.
+ */
+@VintfStability
+union Parameter {
+    /**
+     * Client can pass in Parameter.Id with the corresponding tag value in IEffect.getParameter()
+     * call to get android.hardware.audio.effect.Parameter.
+     *
+     * As an example, if a client want to get audio.hardware.audio.effect.Specific.Equalizer, the
+     * value of Id should be audio.hardware.audio.effect.Parameter.Specific.equalizer.
+     */
+    @VintfStability
+    union Id {
+        /**
+         *  Common parameter tag.
+         */
+        int commonTag;
+        /**
+         * Vendor defined parameter tag.
+         */
+        int vendorTag;
+        /**
+         * Specific effect parameter tag.
+         */
+        Specific.Id specificId;
+    }
+
+    /**
+     * Common parameters MUST be supported by all effect implementations.
+     */
+    @VintfStability
+    parcelable Common {
+        /**
+         * Type of Audio device.
+         */
+        int session;
+        /**
+         * I/O Handle.
+         */
+        int ioHandle;
+        /**
+         * Input config.
+         */
+        AudioConfig input;
+        /**
+         * Output config.
+         */
+        AudioConfig output;
+    }
+    Common common;
+
+    /**
+     * Used by audio framework to set the device type to effect engine.
+     * Effect must implement setParameter(device) if Flags.deviceIndication set to true.
+     */
+    AudioDeviceType device;
+    /**
+     * Used by audio framework to set the audio mode to effect engine.
+     * Effect must implement setParameter(mode) if Flags.audioModeIndication set to true.
+     */
+    AudioMode mode;
+    /**
+     * Used by audio framework to set the audio source to effect engine.
+     * Effect must implement setParameter(source) if Flags.audioSourceIndication set to true.
+     */
+    AudioSource source;
+
+    /**
+     * The volume gain for left and right channel, left and right equals to same value if it's mono.
+     */
+    @VintfStability
+    parcelable Volume {
+        float left;
+        float right;
+    }
+    /**
+     * Used by audio framework to delegate volume control to effect engine.
+     * Effect must implement setParameter(volume) if Flags.volume set to Volume.IND.
+     */
+    Volume volume;
+
+    /**
+     * Used by audio framework to delegate offload information to effect engine.
+     * Effect must implement setParameter(offload) if Flags.offloadSupported set to true.
+     */
+    boolean offload;
+
+    /**
+     * Parameters for vendor extension effect implementation usage.
+     */
+    @VintfStability
+    parcelable VendorEffectParameter {
+        ParcelableHolder extension;
+    }
+    VendorEffectParameter vendorEffect;
+
+    /**
+     * Parameters MUST be supported by a Specific type of effect.
+     */
+    @VintfStability
+    union Specific {
+        @VintfStability
+        union Id {
+            /**
+             * Equalizer.Tag to identify the parameters in Equalizer.
+             */
+            Equalizer.Tag equalizerTag = Equalizer.Tag.vendor;
+        }
+        Id id;
+
+        Equalizer equalizer;
+    }
+    Specific specific;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Processing.aidl b/audio/aidl/android/hardware/audio/effect/Processing.aidl
new file mode 100644
index 0000000..ef32e8c
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Processing.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.Descriptor;
+import android.media.audio.common.AudioSource;
+import android.media.audio.common.AudioStreamType;
+import android.media.audio.common.AudioUuid;
+
+/**
+ * List of effects which must be used for certain pre-processing or post-processing.
+ */
+@VintfStability
+parcelable Processing {
+    @VintfStability
+    union Type {
+        AudioStreamType streamType = AudioStreamType.INVALID;
+        AudioSource source;
+    }
+
+    /**
+     * Specifies the type of processing by referring to the output stream type (AudioStreamType) or
+     * the input stream source (AudioSource).
+     */
+    Type type;
+    /**
+     * List of effect identities for this processing.
+     */
+    Descriptor.Identity[] ids;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/State.aidl b/audio/aidl/android/hardware/audio/effect/State.aidl
new file mode 100644
index 0000000..85a4afc
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/State.aidl
@@ -0,0 +1,86 @@
+/*
+ * 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;
+
+/**
+ * Possible states of an effect instance.
+ * A typical effect instance will be in INIT state when it is created with IFactory.createEffect()
+ * interface, transfer to IDLE after open(), and to PROCESSING after
+ * IEffect.command(Command.Id.START) command. When an effect instance receive STOP or RESET command,
+ * it should transfer to IDLE state after handle the command successfully. Effect instance should
+ * consume minimal resource and transfer to INIT state after it was close().
+ *
+ * Refer to State.gv for detailed state diagram.
+ */
+@VintfStability
+@Backing(type="byte")
+enum State {
+
+    /**
+     * An effect instance is in INIT state by default after it was created with
+     * IFactory.createEffect(). When an effect instance is in INIT state, it should have instance
+     * context initialized, and ready to handle IEffect.setParameter(), IEffect.open() as well as
+     * all getter interfaces.
+     *
+     * In INIT state, effect instance must:
+     * 1. Not handle any IEffect.command() and return EX_ILLEGAL_STATE with any Command.Id.
+     * 2. Be able to handle all parameter setting with IEffect.setParameter().
+     * 3. Be able to handle all getter interface calls like IEffect.getParameter() and
+     * IEffect.getState().
+     * 4. Be able to handle IEffect.open() successfully after configuration.
+     *
+     * Client is expected to do necessary configuration with IEffect.setParameter(), get all
+     * resource ready with IEffect.open(), and make sure effect instance transfer to IDLE state
+     * before sending commands with IEffect.command() interface. Effect instance must transfer
+     * from INIT to IDLE state after handle IEffect.open() call successfully.
+     */
+    INIT,
+    /**
+     * An effect instance transfer to IDLE state after it was open successfully with IEffect.open()
+     * in INIT state, or after it was stop/reset with Command.Id.STOP/RESET in PROCESSING state.
+     *
+     * In IDLE state, effect instance must:
+     * 1. Be able to start effect processing engine with IEffect.command(Command.Id.START) call.
+     * 2. Be able to handle all parameter setting with IEffect.setParameter().
+     * 3. Be able to handle all getter interface calls like IEffect.getParameter() and
+     * IEffect.getState().
+     *
+     * The following state transfer can happen in IDLE state:
+     * 1. Transfer to PROCESSING if instance receive an START command and start processing data
+     * successfully.
+     * 2. Transfer to INIT if instance receive a close() call.
+     */
+    IDLE,
+    /**
+     * An effect instance is in PROCESSING state after it receive an START command and start
+     * processing data successfully. Effect instance will transfer from PROCESSING to IDLE state if
+     * it receive an STOP or RESET command and handle the command successfully.
+     *
+     * When an instance is in PROCESSING state, client should try not to close() it directly,
+     * instead client should try to stop processing data first with STOP command before close(). In
+     * the case of a close() call received when instance in PROCESSING state, it should try to stop
+     * processing and transfer to IDLE first before close().
+     *
+     * In PROCESSING state, effect instance must:
+     * 1. Return EX_ILLEGAL_STATE if it's not able to handle any parameter settings at runtime.
+     * 2. Be able to handle STOP and RESET for IEffect.command() interface, and return
+     * EX_ILLEGAL_STATE for all other commands.
+     * 3. Must be able to handle all get* interface calls like IEffect.getParameter() and
+     * IEffect.getState().
+     */
+    PROCESSING,
+}
diff --git a/audio/aidl/android/hardware/audio/effect/state.gv b/audio/aidl/android/hardware/audio/effect/state.gv
new file mode 100644
index 0000000..e19e6c7
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/state.gv
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+// To render: "dot -Tpng state.gv -o state.png"
+digraph effect_state_machine {
+    node [shape=point style=filled fillcolor=black width=0.5] I;
+    node [shape=doublecircle] F;
+    node [shape=oval width=1];
+    node [fillcolor=lightgreen] INIT;
+    node [fillcolor=lightblue] IDLE;
+    node [fillcolor=lightyellow] PROCESSING;
+
+    I -> INIT [label="IFactory.createEffect" labelfontcolor="navy"];
+    INIT -> F [label="IFactory.destroyEffect"];
+    INIT -> IDLE [label="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
diff --git a/audio/aidl/common/Android.bp b/audio/aidl/common/Android.bp
new file mode 100644
index 0000000..a3f7f0b
--- /dev/null
+++ b/audio/aidl/common/Android.bp
@@ -0,0 +1,68 @@
+/*
+ * 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 {
+    name: "libaudioaidlcommon",
+    host_supported: true,
+    vendor_available: true,
+    export_include_dirs: ["include"],
+    header_libs: [
+        "libbase_headers",
+        "libsystem_headers",
+    ],
+    export_header_lib_headers: [
+        "libbase_headers",
+        "libsystem_headers",
+    ],
+    srcs: [
+        "StreamWorker.cpp",
+    ],
+}
+
+cc_test {
+    name: "libaudioaidlcommon_test",
+    host_supported: true,
+    vendor_available: true,
+    static_libs: [
+        "android.media.audio.common.types-V1-ndk",
+        "libaudioaidlcommon",
+    ],
+    shared_libs: [
+        "liblog",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+    ],
+    srcs: [
+        "tests/streamworker_tests.cpp",
+        "tests/utils_tests.cpp",
+    ],
+    test_suites: [
+        "general-tests",
+    ],
+}
diff --git a/audio/aidl/common/StreamWorker.cpp b/audio/aidl/common/StreamWorker.cpp
new file mode 100644
index 0000000..9bca760
--- /dev/null
+++ b/audio/aidl/common/StreamWorker.cpp
@@ -0,0 +1,160 @@
+/*
+ * 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 <pthread.h>
+#include <sched.h>
+#include <sys/resource.h>
+
+#include "include/StreamWorker.h"
+
+namespace android::hardware::audio::common::internal {
+
+bool ThreadController::start(const std::string& name, int priority) {
+    mThreadName = name;
+    mThreadPriority = priority;
+    mWorker = std::thread(&ThreadController::workerThread, this);
+    std::unique_lock<std::mutex> lock(mWorkerLock);
+    android::base::ScopedLockAssertion lock_assertion(mWorkerLock);
+    mWorkerCv.wait(lock, [&]() {
+        android::base::ScopedLockAssertion lock_assertion(mWorkerLock);
+        return mWorkerState == WorkerState::RUNNING || !mError.empty();
+    });
+    mWorkerStateChangeRequest = false;
+    return mWorkerState == WorkerState::RUNNING;
+}
+
+void ThreadController::stop() {
+    {
+        std::lock_guard<std::mutex> lock(mWorkerLock);
+        if (mWorkerState != WorkerState::STOPPED) {
+            mWorkerState = WorkerState::STOPPED;
+            mWorkerStateChangeRequest = true;
+        }
+    }
+    if (mWorker.joinable()) {
+        mWorker.join();
+    }
+}
+
+bool ThreadController::waitForAtLeastOneCycle() {
+    WorkerState newState;
+    switchWorkerStateSync(WorkerState::RUNNING, WorkerState::PAUSE_REQUESTED, &newState);
+    if (newState != WorkerState::PAUSED) return false;
+    switchWorkerStateSync(newState, WorkerState::RESUME_REQUESTED, &newState);
+    return newState == WorkerState::RUNNING;
+}
+
+void ThreadController::switchWorkerStateSync(WorkerState oldState, WorkerState newState,
+                                             WorkerState* finalState) {
+    std::unique_lock<std::mutex> lock(mWorkerLock);
+    android::base::ScopedLockAssertion lock_assertion(mWorkerLock);
+    if (mWorkerState != oldState) {
+        if (finalState) *finalState = mWorkerState;
+        return;
+    }
+    mWorkerState = newState;
+    mWorkerStateChangeRequest = true;
+    mWorkerCv.wait(lock, [&]() {
+        android::base::ScopedLockAssertion lock_assertion(mWorkerLock);
+        return mWorkerState != newState;
+    });
+    if (finalState) *finalState = mWorkerState;
+}
+
+void ThreadController::workerThread() {
+    using Status = StreamLogic::Status;
+
+    std::string error = mLogic->init();
+    if (error.empty() && !mThreadName.empty()) {
+        std::string compliantName(mThreadName.substr(0, 15));
+        if (int errCode = pthread_setname_np(pthread_self(), compliantName.c_str()); errCode != 0) {
+            error.append("Failed to set thread name: ").append(strerror(errCode));
+        }
+    }
+    if (error.empty() && mThreadPriority != ANDROID_PRIORITY_DEFAULT) {
+        if (int result = setpriority(PRIO_PROCESS, 0, mThreadPriority); result != 0) {
+            int errCode = errno;
+            error.append("Failed to set thread priority: ").append(strerror(errCode));
+        }
+    }
+    {
+        std::lock_guard<std::mutex> lock(mWorkerLock);
+        mWorkerState = error.empty() ? WorkerState::RUNNING : WorkerState::STOPPED;
+        mError = error;
+    }
+    mWorkerCv.notify_one();
+    if (!error.empty()) return;
+
+    for (WorkerState state = WorkerState::RUNNING; state != WorkerState::STOPPED;) {
+        bool needToNotify = false;
+        if (Status status = state != WorkerState::PAUSED ? mLogic->cycle()
+                                                         : (sched_yield(), Status::CONTINUE);
+            status == Status::CONTINUE) {
+            {
+                // See https://developer.android.com/training/articles/smp#nonracing
+                android::base::ScopedLockAssertion lock_assertion(mWorkerLock);
+                if (!mWorkerStateChangeRequest.load(std::memory_order_relaxed)) continue;
+            }
+            //
+            // Pause and resume are synchronous. One worker cycle must complete
+            // before the worker indicates a state change. This is how 'mWorkerState' and
+            // 'state' interact:
+            //
+            // mWorkerState == RUNNING
+            // client sets mWorkerState := PAUSE_REQUESTED
+            // last workerCycle gets executed, state := mWorkerState := PAUSED by us
+            //   (or the workers enters the 'error' state if workerCycle fails)
+            // client gets notified about state change in any case
+            // thread is doing a busy wait while 'state == PAUSED'
+            // client sets mWorkerState := RESUME_REQUESTED
+            // state := mWorkerState (RESUME_REQUESTED)
+            // mWorkerState := RUNNING, but we don't notify the client yet
+            // first workerCycle gets executed, the code below triggers a client notification
+            //   (or if workerCycle fails, worker enters 'error' state and also notifies)
+            // state := mWorkerState (RUNNING)
+            std::lock_guard<std::mutex> lock(mWorkerLock);
+            if (state == WorkerState::RESUME_REQUESTED) {
+                needToNotify = true;
+            }
+            state = mWorkerState;
+            if (mWorkerState == WorkerState::PAUSE_REQUESTED) {
+                state = mWorkerState = WorkerState::PAUSED;
+                needToNotify = true;
+            } else if (mWorkerState == WorkerState::RESUME_REQUESTED) {
+                mWorkerState = WorkerState::RUNNING;
+            }
+        } else {
+            std::lock_guard<std::mutex> lock(mWorkerLock);
+            if (state == WorkerState::RESUME_REQUESTED ||
+                mWorkerState == WorkerState::PAUSE_REQUESTED) {
+                needToNotify = true;
+            }
+            state = mWorkerState = WorkerState::STOPPED;
+            if (status == Status::ABORT) {
+                mError = "Received ABORT from the logic cycle";
+            }
+        }
+        if (needToNotify) {
+            {
+                std::lock_guard<std::mutex> lock(mWorkerLock);
+                mWorkerStateChangeRequest = false;
+            }
+            mWorkerCv.notify_one();
+        }
+    }
+}
+
+}  // namespace android::hardware::audio::common::internal
diff --git a/audio/aidl/common/TEST_MAPPING b/audio/aidl/common/TEST_MAPPING
new file mode 100644
index 0000000..9dcf44e
--- /dev/null
+++ b/audio/aidl/common/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "libaudioaidlcommon_test"
+    }
+  ]
+}
diff --git a/audio/aidl/common/include/StreamWorker.h b/audio/aidl/common/include/StreamWorker.h
new file mode 100644
index 0000000..6260eca
--- /dev/null
+++ b/audio/aidl/common/include/StreamWorker.h
@@ -0,0 +1,153 @@
+/*
+ * 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 <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <string>
+#include <thread>
+
+#include <android-base/thread_annotations.h>
+#include <system/thread_defs.h>
+
+namespace android::hardware::audio::common {
+
+class StreamLogic;
+
+namespace internal {
+
+class ThreadController {
+    enum class WorkerState { STOPPED, RUNNING, PAUSE_REQUESTED, PAUSED, RESUME_REQUESTED };
+
+  public:
+    explicit ThreadController(StreamLogic* logic) : mLogic(logic) {}
+    ~ThreadController() { stop(); }
+
+    bool start(const std::string& name, int priority);
+    void pause() { switchWorkerStateSync(WorkerState::RUNNING, WorkerState::PAUSE_REQUESTED); }
+    void resume() { switchWorkerStateSync(WorkerState::PAUSED, WorkerState::RESUME_REQUESTED); }
+    bool hasError() {
+        std::lock_guard<std::mutex> lock(mWorkerLock);
+        return !mError.empty();
+    }
+    std::string getError() {
+        std::lock_guard<std::mutex> lock(mWorkerLock);
+        return mError;
+    }
+    void stop();
+    bool waitForAtLeastOneCycle();
+
+    // Only used by unit tests.
+    void lockUnlockMutex(bool lock) NO_THREAD_SAFETY_ANALYSIS {
+        lock ? mWorkerLock.lock() : mWorkerLock.unlock();
+    }
+    std::thread::native_handle_type getThreadNativeHandle() { return mWorker.native_handle(); }
+
+  private:
+    void switchWorkerStateSync(WorkerState oldState, WorkerState newState,
+                               WorkerState* finalState = nullptr);
+    void workerThread();
+
+    StreamLogic* const mLogic;
+    std::string mThreadName;
+    int mThreadPriority = ANDROID_PRIORITY_DEFAULT;
+    std::thread mWorker;
+    std::mutex mWorkerLock;
+    std::condition_variable mWorkerCv;
+    WorkerState mWorkerState GUARDED_BY(mWorkerLock) = WorkerState::STOPPED;
+    std::string mError GUARDED_BY(mWorkerLock);
+    // The atomic lock-free variable is used to prevent priority inversions
+    // that can occur when a high priority worker tries to acquire the lock
+    // which has been taken by a lower priority control thread which in its turn
+    // got preempted. To prevent a PI under normal operating conditions, that is,
+    // when there are no errors or state changes, the worker does not attempt
+    // taking `mWorkerLock` unless `mWorkerStateChangeRequest` is set.
+    // To make sure that updates to `mWorkerState` and `mWorkerStateChangeRequest`
+    // are serialized, they are always made under a lock.
+    static_assert(std::atomic<bool>::is_always_lock_free);
+    std::atomic<bool> mWorkerStateChangeRequest GUARDED_BY(mWorkerLock) = false;
+};
+
+}  // namespace internal
+
+class StreamLogic {
+  public:
+    friend class internal::ThreadController;
+
+    virtual ~StreamLogic() = default;
+
+  protected:
+    enum class Status { ABORT, CONTINUE, EXIT };
+
+    /* Called once at the beginning of the thread loop. Must return
+     * an empty string to enter the thread loop, otherwise the thread loop
+     * exits and the worker switches into the 'error' state, setting
+     * the error to the returned value.
+     */
+    virtual std::string init() = 0;
+
+    /* Called for each thread loop unless the thread is in 'paused' state.
+     * Must return 'CONTINUE' to continue running, otherwise the thread loop
+     * exits. If the result from worker cycle is 'ABORT' then the worker switches
+     * into the 'error' state with a generic error message. It is recommended that
+     * the subclass reports any problems via logging facilities. Returning the 'EXIT'
+     * status is equivalent to calling 'stop()' method. This is just a way of
+     * of stopping the worker by its own initiative.
+     */
+    virtual Status cycle() = 0;
+};
+
+template <class LogicImpl>
+class StreamWorker : public LogicImpl {
+  public:
+    template <class... Args>
+    explicit StreamWorker(Args&&... args) : LogicImpl(std::forward<Args>(args)...), mThread(this) {}
+
+    // Methods of LogicImpl are available via inheritance.
+    // Forwarded methods of ThreadController follow.
+
+    // Note that 'priority' here is what is known as the 'nice number' in *nix systems.
+    // The nice number is used with the default scheduler. For threads that
+    // need to use a specialized scheduler (e.g. SCHED_FIFO) and set the priority within it,
+    // it is recommended to implement an appropriate configuration sequence within
+    // 'LogicImpl' or 'StreamLogic::init'.
+    bool start(const std::string& name = "", int priority = ANDROID_PRIORITY_DEFAULT) {
+        return mThread.start(name, priority);
+    }
+    void pause() { mThread.pause(); }
+    void resume() { mThread.resume(); }
+    bool hasError() { return mThread.hasError(); }
+    std::string getError() { return mThread.getError(); }
+    void stop() { return mThread.stop(); }
+    bool waitForAtLeastOneCycle() { return mThread.waitForAtLeastOneCycle(); }
+
+    // Only used by unit tests.
+    void testLockUnlockMutex(bool lock) { mThread.lockUnlockMutex(lock); }
+    std::thread::native_handle_type testGetThreadNativeHandle() {
+        return mThread.getThreadNativeHandle();
+    }
+
+  private:
+    // The ThreadController gets destroyed before LogicImpl.
+    // After the controller has been destroyed, it is guaranteed that
+    // the thread was joined, thus the 'cycle' method of LogicImpl
+    // will not be called anymore, and it is safe to destroy LogicImpl.
+    internal::ThreadController mThread;
+};
+
+}  // namespace android::hardware::audio::common
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
new file mode 100644
index 0000000..1026134
--- /dev/null
+++ b/audio/aidl/common/include/Utils.h
@@ -0,0 +1,116 @@
+/*
+ * 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 <initializer_list>
+#include <type_traits>
+
+#include <aidl/android/media/audio/common/AudioChannelLayout.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>
+#include <aidl/android/media/audio/common/PcmType.h>
+
+namespace android::hardware::audio::common {
+
+constexpr size_t getPcmSampleSizeInBytes(::aidl::android::media::audio::common::PcmType pcm) {
+    using ::aidl::android::media::audio::common::PcmType;
+    switch (pcm) {
+        case PcmType::UINT_8_BIT:
+            return 1;
+        case PcmType::INT_16_BIT:
+            return 2;
+        case PcmType::INT_32_BIT:
+            return 4;
+        case PcmType::FIXED_Q_8_24:
+            return 4;
+        case PcmType::FLOAT_32_BIT:
+            return 4;
+        case PcmType::INT_24_BIT:
+            return 3;
+    }
+    return 0;
+}
+
+constexpr size_t getChannelCount(
+        const ::aidl::android::media::audio::common::AudioChannelLayout& layout) {
+    using Tag = ::aidl::android::media::audio::common::AudioChannelLayout::Tag;
+    switch (layout.getTag()) {
+        case Tag::none:
+            return 0;
+        case Tag::invalid:
+            return 0;
+        case Tag::indexMask:
+            return __builtin_popcount(layout.get<Tag::indexMask>());
+        case Tag::layoutMask:
+            return __builtin_popcount(layout.get<Tag::layoutMask>());
+        case Tag::voiceMask:
+            return __builtin_popcount(layout.get<Tag::voiceMask>());
+    }
+    return 0;
+}
+
+constexpr size_t getFrameSizeInBytes(
+        const ::aidl::android::media::audio::common::AudioFormatDescription& format,
+        const ::aidl::android::media::audio::common::AudioChannelLayout& layout) {
+    if (format == ::aidl::android::media::audio::common::AudioFormatDescription{}) {
+        // Unspecified format.
+        return 0;
+    }
+    using ::aidl::android::media::audio::common::AudioFormatType;
+    if (format.type == AudioFormatType::PCM) {
+        return getPcmSampleSizeInBytes(format.pcm) * getChannelCount(layout);
+    } else if (format.type == AudioFormatType::NON_PCM) {
+        // For non-PCM formats always use the underlying PCM size. The default value for
+        // PCM is "UINT_8_BIT", thus non-encapsulated streams have the frame size of 1.
+        return getPcmSampleSizeInBytes(format.pcm);
+    }
+    // Something unexpected.
+    return 0;
+}
+
+// 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.
+template <typename E>
+using is_bit_position_enum = std::integral_constant<
+        bool, std::is_same_v<E, ::aidl::android::media::audio::common::AudioInputFlags> ||
+                      std::is_same_v<E, ::aidl::android::media::audio::common::AudioOutputFlags>>;
+
+template <typename E, typename U = std::underlying_type_t<E>,
+          typename = std::enable_if_t<is_bit_position_enum<E>::value>>
+constexpr U makeBitPositionFlagMask(E flag) {
+    return 1 << static_cast<U>(flag);
+}
+
+template <typename E, typename U = std::underlying_type_t<E>,
+          typename = std::enable_if_t<is_bit_position_enum<E>::value>>
+constexpr bool isBitPositionFlagSet(U mask, E flag) {
+    return (mask & makeBitPositionFlagMask(flag)) != 0;
+}
+
+template <typename E, typename U = std::underlying_type_t<E>,
+          typename = std::enable_if_t<is_bit_position_enum<E>::value>>
+constexpr U makeBitPositionFlagMask(std::initializer_list<E> flags) {
+    U result = 0;
+    for (const auto flag : flags) {
+        result |= makeBitPositionFlagMask(flag);
+    }
+    return result;
+}
+
+}  // namespace android::hardware::audio::common
diff --git a/audio/aidl/common/tests/streamworker_tests.cpp b/audio/aidl/common/tests/streamworker_tests.cpp
new file mode 100644
index 0000000..e3e484d
--- /dev/null
+++ b/audio/aidl/common/tests/streamworker_tests.cpp
@@ -0,0 +1,278 @@
+/*
+ * 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 <pthread.h>
+#include <sched.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+#include <atomic>
+
+#include <StreamWorker.h>
+
+#include <gtest/gtest.h>
+#define LOG_TAG "StreamWorker_Test"
+#include <log/log.h>
+
+using android::hardware::audio::common::StreamLogic;
+using android::hardware::audio::common::StreamWorker;
+
+class TestWorkerLogic : public StreamLogic {
+  public:
+    struct Stream {
+        void setErrorStatus() { status = Status::ABORT; }
+        void setStopStatus() { status = Status::EXIT; }
+        std::atomic<Status> status = Status::CONTINUE;
+    };
+
+    // Use nullptr to test error reporting from the worker thread.
+    explicit TestWorkerLogic(Stream* stream) : mStream(stream) {}
+
+    size_t getWorkerCycles() const { return mWorkerCycles; }
+    int getPriority() const { return mPriority; }
+    bool hasWorkerCycleCalled() const { return mWorkerCycles != 0; }
+    bool hasNoWorkerCycleCalled(useconds_t usec) {
+        const size_t cyclesBefore = mWorkerCycles;
+        usleep(usec);
+        return mWorkerCycles == cyclesBefore;
+    }
+
+  protected:
+    // StreamLogic implementation
+    std::string init() override { return mStream != nullptr ? "" : "Expected error"; }
+    Status cycle() override {
+        mPriority = getpriority(PRIO_PROCESS, 0);
+        do {
+            mWorkerCycles++;
+        } while (mWorkerCycles == 0);
+        return mStream->status;
+    }
+
+  private:
+    Stream* const mStream;
+    std::atomic<size_t> mWorkerCycles = 0;
+    std::atomic<int> mPriority = ANDROID_PRIORITY_DEFAULT;
+};
+using TestWorker = StreamWorker<TestWorkerLogic>;
+
+// The parameter specifies whether an extra call to 'stop' is made at the end.
+class StreamWorkerInvalidTest : public testing::TestWithParam<bool> {
+  public:
+    StreamWorkerInvalidTest() : StreamWorkerInvalidTest(nullptr) {}
+    void TearDown() override {
+        if (GetParam()) {
+            worker.stop();
+        }
+    }
+
+  protected:
+    StreamWorkerInvalidTest(TestWorker::Stream* stream)
+        : testing::TestWithParam<bool>(), worker(stream) {}
+    TestWorker worker;
+};
+
+TEST_P(StreamWorkerInvalidTest, Uninitialized) {
+    EXPECT_FALSE(worker.hasWorkerCycleCalled());
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, UninitializedPauseIgnored) {
+    EXPECT_FALSE(worker.hasError());
+    worker.pause();
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, UninitializedResumeIgnored) {
+    EXPECT_FALSE(worker.hasError());
+    worker.resume();
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, Start) {
+    EXPECT_FALSE(worker.start());
+    EXPECT_FALSE(worker.hasWorkerCycleCalled());
+    EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, PauseIgnored) {
+    EXPECT_FALSE(worker.start());
+    EXPECT_TRUE(worker.hasError());
+    worker.pause();
+    EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerInvalidTest, ResumeIgnored) {
+    EXPECT_FALSE(worker.start());
+    EXPECT_TRUE(worker.hasError());
+    worker.resume();
+    EXPECT_TRUE(worker.hasError());
+}
+
+INSTANTIATE_TEST_SUITE_P(StreamWorkerInvalid, StreamWorkerInvalidTest, testing::Bool());
+
+class StreamWorkerTest : public StreamWorkerInvalidTest {
+  public:
+    StreamWorkerTest() : StreamWorkerInvalidTest(&stream) {}
+
+  protected:
+    TestWorker::Stream stream;
+};
+
+static constexpr unsigned kWorkerIdleCheckTime = 50 * 1000;
+
+TEST_P(StreamWorkerTest, Uninitialized) {
+    EXPECT_FALSE(worker.hasWorkerCycleCalled());
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, Start) {
+    ASSERT_TRUE(worker.start());
+    EXPECT_TRUE(worker.waitForAtLeastOneCycle());
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, StartStop) {
+    ASSERT_TRUE(worker.start());
+    EXPECT_TRUE(worker.waitForAtLeastOneCycle());
+    EXPECT_FALSE(worker.hasError());
+    worker.stop();
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, WorkerExit) {
+    ASSERT_TRUE(worker.start());
+    stream.setStopStatus();
+    worker.waitForAtLeastOneCycle();
+    EXPECT_FALSE(worker.hasError());
+    EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+}
+
+TEST_P(StreamWorkerTest, WorkerError) {
+    ASSERT_TRUE(worker.start());
+    stream.setErrorStatus();
+    worker.waitForAtLeastOneCycle();
+    EXPECT_TRUE(worker.hasError());
+    EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+}
+
+TEST_P(StreamWorkerTest, StopAfterError) {
+    ASSERT_TRUE(worker.start());
+    stream.setErrorStatus();
+    worker.waitForAtLeastOneCycle();
+    EXPECT_TRUE(worker.hasError());
+    EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+    worker.stop();
+    EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, PauseResume) {
+    ASSERT_TRUE(worker.start());
+    EXPECT_TRUE(worker.waitForAtLeastOneCycle());
+    EXPECT_FALSE(worker.hasError());
+    worker.pause();
+    EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+    EXPECT_FALSE(worker.hasError());
+    const size_t workerCyclesBefore = worker.getWorkerCycles();
+    worker.resume();
+    // 'resume' is synchronous and returns after the worker has looped at least once.
+    EXPECT_GT(worker.getWorkerCycles(), workerCyclesBefore);
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, StopPaused) {
+    ASSERT_TRUE(worker.start());
+    EXPECT_TRUE(worker.waitForAtLeastOneCycle());
+    EXPECT_FALSE(worker.hasError());
+    worker.pause();
+    worker.stop();
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, PauseAfterErrorIgnored) {
+    ASSERT_TRUE(worker.start());
+    stream.setErrorStatus();
+    worker.waitForAtLeastOneCycle();
+    EXPECT_TRUE(worker.hasError());
+    worker.pause();
+    EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+    EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, ResumeAfterErrorIgnored) {
+    ASSERT_TRUE(worker.start());
+    stream.setErrorStatus();
+    worker.waitForAtLeastOneCycle();
+    EXPECT_TRUE(worker.hasError());
+    worker.resume();
+    EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+    EXPECT_TRUE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, WorkerErrorOnResume) {
+    ASSERT_TRUE(worker.start());
+    EXPECT_TRUE(worker.waitForAtLeastOneCycle());
+    EXPECT_FALSE(worker.hasError());
+    worker.pause();
+    EXPECT_FALSE(worker.hasError());
+    stream.setErrorStatus();
+    EXPECT_FALSE(worker.hasError());
+    worker.resume();
+    worker.waitForAtLeastOneCycle();
+    EXPECT_TRUE(worker.hasError());
+    EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+}
+
+TEST_P(StreamWorkerTest, WaitForAtLeastOneCycle) {
+    ASSERT_TRUE(worker.start());
+    const size_t workerCyclesBefore = worker.getWorkerCycles();
+    EXPECT_TRUE(worker.waitForAtLeastOneCycle());
+    EXPECT_GT(worker.getWorkerCycles(), workerCyclesBefore);
+}
+
+TEST_P(StreamWorkerTest, WaitForAtLeastOneCycleError) {
+    ASSERT_TRUE(worker.start());
+    stream.setErrorStatus();
+    EXPECT_FALSE(worker.waitForAtLeastOneCycle());
+}
+
+TEST_P(StreamWorkerTest, MutexDoesNotBlockWorker) {
+    ASSERT_TRUE(worker.start());
+    const size_t workerCyclesBefore = worker.getWorkerCycles();
+    worker.testLockUnlockMutex(true);
+    while (worker.getWorkerCycles() == workerCyclesBefore) {
+        usleep(kWorkerIdleCheckTime);
+    }
+    worker.testLockUnlockMutex(false);
+    EXPECT_TRUE(worker.waitForAtLeastOneCycle());
+    EXPECT_FALSE(worker.hasError());
+}
+
+TEST_P(StreamWorkerTest, ThreadName) {
+    const std::string workerName = "TestWorker";
+    ASSERT_TRUE(worker.start(workerName)) << worker.getError();
+    char nameBuf[128];
+    ASSERT_EQ(0, pthread_getname_np(worker.testGetThreadNativeHandle(), nameBuf, sizeof(nameBuf)));
+    EXPECT_EQ(workerName, nameBuf);
+}
+
+TEST_P(StreamWorkerTest, ThreadPriority) {
+    const int priority = ANDROID_PRIORITY_LOWEST;
+    ASSERT_TRUE(worker.start("", priority)) << worker.getError();
+    EXPECT_TRUE(worker.waitForAtLeastOneCycle());
+    EXPECT_EQ(priority, worker.getPriority());
+}
+
+INSTANTIATE_TEST_SUITE_P(StreamWorker, StreamWorkerTest, testing::Bool());
diff --git a/audio/aidl/common/tests/utils_tests.cpp b/audio/aidl/common/tests/utils_tests.cpp
new file mode 100644
index 0000000..d7f1a5d
--- /dev/null
+++ b/audio/aidl/common/tests/utils_tests.cpp
@@ -0,0 +1,190 @@
+/*
+ * 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 <cstdint>
+#include <limits>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include <Utils.h>
+
+#include <gtest/gtest.h>
+#define LOG_TAG "Utils_Test"
+#include <log/log.h>
+
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::PcmType;
+using android::hardware::audio::common::getChannelCount;
+using android::hardware::audio::common::getFrameSizeInBytes;
+using android::hardware::audio::common::getPcmSampleSizeInBytes;
+
+TEST(UtilsTest, ChannelCountOddCases) {
+    using Tag = AudioChannelLayout::Tag;
+    EXPECT_EQ(0UL, getChannelCount(AudioChannelLayout{}));
+    EXPECT_EQ(0UL, getChannelCount(AudioChannelLayout::make<Tag::invalid>(0)));
+    EXPECT_EQ(0UL, getChannelCount(AudioChannelLayout::make<Tag::invalid>(-1)));
+}
+
+TEST(UtilsTest, ChannelCountForIndexMask) {
+    using Tag = AudioChannelLayout::Tag;
+    EXPECT_EQ(0UL, getChannelCount(AudioChannelLayout::make<Tag::indexMask>(0)));
+#define VERIFY_INDEX_MASK(N)                                                                  \
+    {                                                                                         \
+        const auto l =                                                                        \
+                AudioChannelLayout::make<Tag::indexMask>(AudioChannelLayout::INDEX_MASK_##N); \
+        EXPECT_EQ(N##UL, getChannelCount(l)) << l.toString();                                 \
+    }
+    VERIFY_INDEX_MASK(1);
+    VERIFY_INDEX_MASK(2);
+    VERIFY_INDEX_MASK(3);
+    VERIFY_INDEX_MASK(4);
+    VERIFY_INDEX_MASK(5);
+    VERIFY_INDEX_MASK(6);
+    VERIFY_INDEX_MASK(7);
+    VERIFY_INDEX_MASK(8);
+    VERIFY_INDEX_MASK(9);
+    VERIFY_INDEX_MASK(10);
+    VERIFY_INDEX_MASK(11);
+    VERIFY_INDEX_MASK(12);
+    VERIFY_INDEX_MASK(13);
+    VERIFY_INDEX_MASK(14);
+    VERIFY_INDEX_MASK(15);
+    VERIFY_INDEX_MASK(16);
+    VERIFY_INDEX_MASK(17);
+    VERIFY_INDEX_MASK(18);
+    VERIFY_INDEX_MASK(19);
+    VERIFY_INDEX_MASK(20);
+    VERIFY_INDEX_MASK(21);
+    VERIFY_INDEX_MASK(22);
+    VERIFY_INDEX_MASK(23);
+    VERIFY_INDEX_MASK(24);
+#undef VERIFY_INDEX_MASK
+}
+
+TEST(UtilsTest, ChannelCountForLayoutMask) {
+    using Tag = AudioChannelLayout::Tag;
+    const std::vector<std::pair<size_t, int32_t>> kTestLayouts = {
+            std::make_pair(0UL, 0),
+            std::make_pair(1UL, AudioChannelLayout::LAYOUT_MONO),
+            std::make_pair(2UL, AudioChannelLayout::LAYOUT_STEREO),
+            std::make_pair(6UL, AudioChannelLayout::LAYOUT_5POINT1),
+            std::make_pair(8UL, AudioChannelLayout::LAYOUT_7POINT1),
+            std::make_pair(16UL, AudioChannelLayout::LAYOUT_9POINT1POINT6),
+            std::make_pair(13UL, AudioChannelLayout::LAYOUT_13POINT_360RA),
+            std::make_pair(24UL, AudioChannelLayout::LAYOUT_22POINT2),
+            std::make_pair(3UL, AudioChannelLayout::LAYOUT_STEREO_HAPTIC_A),
+            std::make_pair(4UL, AudioChannelLayout::LAYOUT_STEREO_HAPTIC_AB)};
+    for (const auto& [expected_count, layout] : kTestLayouts) {
+        const auto l = AudioChannelLayout::make<Tag::layoutMask>(layout);
+        EXPECT_EQ(expected_count, getChannelCount(l)) << l.toString();
+    }
+}
+
+TEST(UtilsTest, ChannelCountForVoiceMask) {
+    using Tag = AudioChannelLayout::Tag;
+    // clang-format off
+    const std::vector<std::pair<size_t, int32_t>> kTestLayouts = {
+            std::make_pair(0UL, 0),
+            std::make_pair(1UL, AudioChannelLayout::VOICE_UPLINK_MONO),
+            std::make_pair(1UL, AudioChannelLayout::VOICE_DNLINK_MONO),
+            std::make_pair(2UL, AudioChannelLayout::VOICE_CALL_MONO)};
+    // clang-format on
+    for (const auto& [expected_count, layout] : kTestLayouts) {
+        const auto l = AudioChannelLayout::make<Tag::voiceMask>(layout);
+        EXPECT_EQ(expected_count, getChannelCount(l)) << l.toString();
+    }
+}
+
+namespace {
+
+AudioChannelLayout make_AudioChannelLayout_Mono() {
+    return AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+            AudioChannelLayout::LAYOUT_MONO);
+}
+
+AudioChannelLayout make_AudioChannelLayout_Stereo() {
+    return AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+            AudioChannelLayout::LAYOUT_STEREO);
+}
+
+AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
+    AudioFormatDescription result;
+    result.type = type;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
+    auto result = make_AudioFormatDescription(AudioFormatType::PCM);
+    result.pcm = pcm;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
+    AudioFormatDescription result;
+    result.encoding = encoding;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType transport, const std::string& encoding) {
+    auto result = make_AudioFormatDescription(encoding);
+    result.pcm = transport;
+    return result;
+}
+
+}  // namespace
+
+TEST(UtilsTest, FrameSize) {
+    EXPECT_EQ(0UL, getFrameSizeInBytes(AudioFormatDescription{}, AudioChannelLayout{}));
+    EXPECT_EQ(sizeof(int16_t), getFrameSizeInBytes(make_AudioFormatDescription(PcmType::INT_16_BIT),
+                                                   make_AudioChannelLayout_Mono()));
+    EXPECT_EQ(2 * sizeof(int16_t),
+              getFrameSizeInBytes(make_AudioFormatDescription(PcmType::INT_16_BIT),
+                                  make_AudioChannelLayout_Stereo()));
+    EXPECT_EQ(sizeof(int32_t), getFrameSizeInBytes(make_AudioFormatDescription(PcmType::INT_32_BIT),
+                                                   make_AudioChannelLayout_Mono()));
+    EXPECT_EQ(2 * sizeof(int32_t),
+              getFrameSizeInBytes(make_AudioFormatDescription(PcmType::INT_32_BIT),
+                                  make_AudioChannelLayout_Stereo()));
+    EXPECT_EQ(sizeof(float), getFrameSizeInBytes(make_AudioFormatDescription(PcmType::FLOAT_32_BIT),
+                                                 make_AudioChannelLayout_Mono()));
+    EXPECT_EQ(2 * sizeof(float),
+              getFrameSizeInBytes(make_AudioFormatDescription(PcmType::FLOAT_32_BIT),
+                                  make_AudioChannelLayout_Stereo()));
+    EXPECT_EQ(sizeof(uint8_t),
+              getFrameSizeInBytes(make_AudioFormatDescription("bitstream"), AudioChannelLayout{}));
+    EXPECT_EQ(sizeof(int16_t),
+              getFrameSizeInBytes(make_AudioFormatDescription(PcmType::INT_16_BIT, "encapsulated"),
+                                  AudioChannelLayout{}));
+}
+
+TEST(UtilsTest, PcmSampleSize) {
+    EXPECT_EQ(1UL, getPcmSampleSizeInBytes(PcmType{}));
+    EXPECT_EQ(sizeof(uint8_t), getPcmSampleSizeInBytes(PcmType::UINT_8_BIT));
+    EXPECT_EQ(sizeof(int16_t), getPcmSampleSizeInBytes(PcmType::INT_16_BIT));
+    EXPECT_EQ(sizeof(int32_t), getPcmSampleSizeInBytes(PcmType::INT_32_BIT));
+    EXPECT_EQ(sizeof(int32_t), getPcmSampleSizeInBytes(PcmType::FIXED_Q_8_24));
+    EXPECT_EQ(sizeof(float), getPcmSampleSizeInBytes(PcmType::FLOAT_32_BIT));
+    EXPECT_EQ(3UL, getPcmSampleSizeInBytes(PcmType::INT_24_BIT));
+    EXPECT_EQ(0UL, getPcmSampleSizeInBytes(PcmType(-1)));
+    using PcmTypeUnderlyingType = std::underlying_type_t<PcmType>;
+    EXPECT_EQ(0UL,
+              getPcmSampleSizeInBytes(PcmType(std::numeric_limits<PcmTypeUnderlyingType>::min())));
+    EXPECT_EQ(0UL,
+              getPcmSampleSizeInBytes(PcmType(std::numeric_limits<PcmTypeUnderlyingType>::max())));
+}
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
new file mode 100644
index 0000000..e64b90c
--- /dev/null
+++ b/audio/aidl/default/Android.bp
@@ -0,0 +1,121 @@
+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_defaults {
+    name: "aidlaudioservice_defaults",
+    vendor: true,
+    shared_libs: [
+        "libaudioaidlcommon",
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "libfmq",
+        "libstagefright_foundation",
+        "libutils",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+    ],
+    header_libs: [
+        "libaudioaidl_headers",
+    ],
+}
+
+cc_library_static {
+    name: "libaudioserviceexampleimpl",
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_media_audio_common_types_ndk_shared",
+        "latest_android_hardware_audio_core_ndk_shared",
+    ],
+    export_include_dirs: ["include"],
+    srcs: [
+        "Config.cpp",
+        "Configuration.cpp",
+        "Module.cpp",
+        "Stream.cpp",
+    ],
+    visibility: [
+        ":__subpackages__",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.audio.service-aidl.example",
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.audio.service-aidl.example.rc"],
+    vintf_fragments: ["android.hardware.audio.service-aidl.xml"],
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_media_audio_common_types_ndk_shared",
+        "latest_android_hardware_audio_core_ndk_shared",
+    ],
+    static_libs: [
+        "libaudioserviceexampleimpl",
+    ],
+    srcs: ["main.cpp"],
+}
+
+cc_defaults {
+    name: "aidlaudioeffectservice_defaults",
+    defaults: [
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "android.hardware.audio.effect-V1-ndk",
+        "libequalizer",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+    ],
+}
+
+cc_library_static {
+    name: "libaudioeffectserviceexampleimpl",
+    defaults: ["aidlaudioeffectservice_defaults"],
+    export_include_dirs: ["include"],
+    srcs: [
+        "EffectFactory.cpp",
+    ],
+    header_libs: [
+        "libsystem_headers",
+    ],
+    visibility: [
+        ":__subpackages__",
+    ],
+}
+
+filegroup {
+    name: "effectCommonFile",
+    srcs: ["EffectThread.cpp"],
+}
+
+cc_binary {
+    name: "android.hardware.audio.effect.service-aidl.example",
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.audio.effect.service-aidl.example.rc"],
+    vintf_fragments: ["android.hardware.audio.effect.service-aidl.xml"],
+    defaults: ["aidlaudioeffectservice_defaults"],
+    static_libs: [
+        "libaudioeffectserviceexampleimpl",
+    ],
+    srcs: ["EffectMain.cpp"],
+}
+
+cc_library_headers {
+    name: "libaudioaidl_headers",
+    export_include_dirs: ["include"],
+    vendor_available: true,
+    host_supported: true,
+}
diff --git a/audio/aidl/default/Config.cpp b/audio/aidl/default/Config.cpp
new file mode 100644
index 0000000..0fdd5b4
--- /dev/null
+++ b/audio/aidl/default/Config.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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 "AHAL_Module"
+#include <android-base/logging.h>
+
+#include "core-impl/Config.h"
+
+namespace aidl::android::hardware::audio::core {
+ndk::ScopedAStatus Config::getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) {
+    SurroundSoundConfig surroundSoundConfig;
+    // TODO: parse from XML; for now, use empty config as default
+    *_aidl_return = std::move(surroundSoundConfig);
+    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
new file mode 100644
index 0000000..a3e5ff7
--- /dev/null
+++ b/audio/aidl/default/Configuration.cpp
@@ -0,0 +1,292 @@
+/*
+ * 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 <Utils.h>
+#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/AudioFormatType.h>
+#include <aidl/android/media/audio/common/AudioIoFlags.h>
+#include <aidl/android/media/audio/common/AudioOutputFlags.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+
+#include "core-impl/Configuration.h"
+
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioGainConfig;
+using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioOutputFlags;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::AudioPortDeviceExt;
+using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioPortMixExt;
+using aidl::android::media::audio::common::AudioProfile;
+using aidl::android::media::audio::common::Int;
+using aidl::android::media::audio::common::PcmType;
+using android::hardware::audio::common::makeBitPositionFlagMask;
+
+namespace aidl::android::hardware::audio::core::internal {
+
+static void fillProfile(AudioProfile* profile, const std::vector<int32_t>& channelLayouts,
+                        const std::vector<int32_t>& sampleRates) {
+    for (auto layout : channelLayouts) {
+        profile->channelMasks.push_back(
+                AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout));
+    }
+    profile->sampleRates.insert(profile->sampleRates.end(), sampleRates.begin(), sampleRates.end());
+}
+
+static AudioProfile createProfile(PcmType pcmType, const std::vector<int32_t>& channelLayouts,
+                                  const std::vector<int32_t>& sampleRates) {
+    AudioProfile profile;
+    profile.format.type = AudioFormatType::PCM;
+    profile.format.pcm = pcmType;
+    fillProfile(&profile, channelLayouts, sampleRates);
+    return profile;
+}
+
+static AudioProfile createProfile(const std::string& encodingType,
+                                  const std::vector<int32_t>& channelLayouts,
+                                  const std::vector<int32_t>& sampleRates) {
+    AudioProfile profile;
+    profile.format.encoding = encodingType;
+    fillProfile(&profile, channelLayouts, sampleRates);
+    return profile;
+}
+
+static AudioPortExt createDeviceExt(AudioDeviceType devType, int32_t flags,
+                                    std::string connection = "") {
+    AudioPortDeviceExt deviceExt;
+    deviceExt.device.type.type = devType;
+    deviceExt.device.type.connection = std::move(connection);
+    deviceExt.flags = flags;
+    return AudioPortExt::make<AudioPortExt::Tag::device>(deviceExt);
+}
+
+static AudioPortExt createPortMixExt(int32_t maxOpenStreamCount, int32_t maxActiveStreamCount) {
+    AudioPortMixExt mixExt;
+    mixExt.maxOpenStreamCount = maxOpenStreamCount;
+    mixExt.maxActiveStreamCount = maxActiveStreamCount;
+    return AudioPortExt::make<AudioPortExt::Tag::mix>(mixExt);
+}
+
+static AudioPort createPort(int32_t id, const std::string& name, int32_t flags, bool isInput,
+                            const AudioPortExt& ext) {
+    AudioPort port;
+    port.id = id;
+    port.name = name;
+    port.flags = isInput ? AudioIoFlags::make<AudioIoFlags::Tag::input>(flags)
+                         : AudioIoFlags::make<AudioIoFlags::Tag::output>(flags);
+    port.ext = ext;
+    return port;
+}
+
+static AudioPortConfig createPortConfig(int32_t id, int32_t portId, PcmType pcmType, int32_t layout,
+                                        int32_t sampleRate, int32_t flags, bool isInput,
+                                        const AudioPortExt& ext) {
+    AudioPortConfig config;
+    config.id = id;
+    config.portId = portId;
+    config.sampleRate = Int{.value = sampleRate};
+    config.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout);
+    config.format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType};
+    config.gain = AudioGainConfig();
+    config.flags = isInput ? AudioIoFlags::make<AudioIoFlags::Tag::input>(flags)
+                           : AudioIoFlags::make<AudioIoFlags::Tag::output>(flags);
+    config.ext = ext;
+    return config;
+}
+
+static AudioRoute createRoute(const std::vector<int32_t>& sources, int32_t sink) {
+    AudioRoute route;
+    route.sinkPortId = sink;
+    route.sourcePortIds.insert(route.sourcePortIds.end(), sources.begin(), sources.end());
+    return route;
+}
+
+// Configuration:
+//
+// Device ports:
+//  * "Null", OUT_SPEAKER, default
+//    - no profiles specified
+//  * "Loopback Out", OUT_SUBMIX
+//    - profile PCM 24-bit; STEREO; 48000
+//  * "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
+//  * "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
+//
+// Routes:
+//  "primary out", "compressed offload" -> "Null"
+//  "primary out", "compressed offload" -> "USB Out"
+//  "loopback out" -> "Loopback Out"
+//  "Zero", "USB In" -> "primary input"
+//  "Loopback In" -> "loopback input"
+//
+// Initial port configs:
+//  * "Null" device port: PCM 24-bit; STEREO; 48000
+//  * "Zero" device port: PCM 24-bit; MONO; 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
+//  * USB In":
+//    - profile PCM 16-bit; MONO, STEREO; 44100, 48000
+//    - profile PCM 24-bit; MONO, STEREO; 44100, 48000
+//
+Configuration& getNullPrimaryConfiguration() {
+    static Configuration configuration = []() {
+        const std::vector<AudioProfile> standardPcmAudioProfiles = {
+                createProfile(PcmType::INT_16_BIT,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+                              {44100, 48000}),
+                createProfile(PcmType::INT_24_BIT,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+                              {44100, 48000})};
+        Configuration c;
+
+        AudioPort nullOutDevice =
+                createPort(c.nextPortId++, "Null", 0, false,
+                           createDeviceExt(AudioDeviceType::OUT_SPEAKER,
+                                           1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
+        c.ports.push_back(nullOutDevice);
+        c.initialConfigs.push_back(
+                createPortConfig(nullOutDevice.id, nullOutDevice.id, PcmType::INT_24_BIT,
+                                 AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
+                                 createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
+
+        AudioPort primaryOutMix = createPort(c.nextPortId++, "primary output",
+                                             makeBitPositionFlagMask(AudioOutputFlags::PRIMARY),
+                                             false, createPortMixExt(1, 1));
+        primaryOutMix.profiles.insert(primaryOutMix.profiles.begin(),
+                                      standardPcmAudioProfiles.begin(),
+                                      standardPcmAudioProfiles.end());
+        c.ports.push_back(primaryOutMix);
+
+        AudioPort compressedOffloadOutMix =
+                createPort(c.nextPortId++, "compressed offload",
+                           makeBitPositionFlagMask({AudioOutputFlags::DIRECT,
+                                                    AudioOutputFlags::COMPRESS_OFFLOAD,
+                                                    AudioOutputFlags::NON_BLOCKING}),
+                           false, createPortMixExt(1, 1));
+        compressedOffloadOutMix.profiles.push_back(
+                createProfile(::android::MEDIA_MIMETYPE_AUDIO_MPEG,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+                              {44100, 48000}));
+        c.ports.push_back(compressedOffloadOutMix);
+
+        AudioPort loopOutDevice = createPort(c.nextPortId++, "Loopback Out", 0, false,
+                                             createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0));
+        loopOutDevice.profiles.push_back(
+                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)));
+
+        AudioPort primaryInMix =
+                createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(2, 2));
+        primaryInMix.profiles.push_back(
+                createProfile(PcmType::INT_16_BIT,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
+                               AudioChannelLayout::LAYOUT_FRONT_BACK},
+                              {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
+        primaryInMix.profiles.push_back(
+                createProfile(PcmType::INT_24_BIT,
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
+                               AudioChannelLayout::LAYOUT_FRONT_BACK},
+                              {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 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 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;
+
+        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.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
+        return c;
+    }();
+    return configuration;
+}
+
+}  // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
new file mode 100644
index 0000000..8e107a2
--- /dev/null
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -0,0 +1,182 @@
+/*
+ * 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 "AHAL_EffectFactory"
+#include <android-base/logging.h>
+#include <dlfcn.h>
+
+#include "effect-impl/EffectUUID.h"
+#include "effectFactory-impl/EffectFactory.h"
+
+using aidl::android::media::audio::common::AudioUuid;
+
+namespace aidl::android::hardware::audio::effect {
+
+Factory::Factory() {
+    std::function<void(void*)> dlClose = [](void* handle) -> void {
+        if (handle && dlclose(handle)) {
+            LOG(ERROR) << "dlclose failed " << dlerror();
+        }
+    };
+    // TODO: implement this with audio_effect.xml.
+    auto libHandle =
+            std::unique_ptr<void, decltype(dlClose)>{dlopen("libequalizer.so", RTLD_LAZY), dlClose};
+    if (!libHandle) {
+        LOG(ERROR) << __func__ << ": dlopen failed, err: " << dlerror();
+        return;
+    }
+
+    LOG(DEBUG) << __func__ << " dlopen uuid: " << EqualizerSwImplUUID.toString() << " handle "
+               << libHandle;
+    mEffectLibMap.insert({EqualizerSwImplUUID, std::make_pair(std::move(libHandle), nullptr)});
+
+    Descriptor::Identity id;
+    id.type = EqualizerTypeUUID;
+    id.uuid = EqualizerSwImplUUID;
+    mIdentityList.push_back(id);
+}
+
+Factory::~Factory() {
+    if (auto count = mEffectUuidMap.size()) {
+        LOG(ERROR) << __func__ << " remaining " << count
+                   << " effect instances not destroyed indicating resource leak!";
+        for (const auto& it : mEffectUuidMap) {
+            if (auto spEffect = it.first.lock()) {
+                LOG(ERROR) << __func__ << " erase remaining instance UUID " << it.second.toString();
+                destroyEffectImpl(spEffect);
+            }
+        }
+    }
+}
+
+ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type_uuid,
+                                         const std::optional<AudioUuid>& in_impl_uuid,
+                                         std::vector<Descriptor::Identity>* _aidl_return) {
+    std::copy_if(mIdentityList.begin(), mIdentityList.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);
+                 });
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Factory::queryProcessing(const std::optional<Processing::Type>& in_type,
+                                            std::vector<Processing>* _aidl_return) {
+    // TODO: implement this with audio_effect.xml.
+    if (in_type.has_value()) {
+        // return all matching process filter
+        LOG(DEBUG) << __func__ << " process type: " << in_type.value().toString();
+    }
+    LOG(DEBUG) << __func__ << " return " << _aidl_return->size();
+    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 (in_impl_uuid == EqualizerSwImplUUID) {
+        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();
+                struct effect_interface_s intf = {
+                        .createEffectFunc = (EffectCreateFunctor)dlsym(libHandle, "createEffect"),
+                        .destroyEffectFunc =
+                                (EffectDestroyFunctor)dlsym(libHandle, "destroyEffect")};
+                auto dlInterface = std::make_unique<struct effect_interface_s>(intf);
+                if (!dlInterface->createEffectFunc || !dlInterface->destroyEffectFunc) {
+                    LOG(ERROR) << __func__
+                               << ": create or destroy symbol not exist in library: " << libHandle
+                               << "!";
+                    return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+                }
+                lib.second = std::move(dlInterface);
+            }
+
+            auto& libInterface = lib.second;
+            std::shared_ptr<IEffect> effectSp;
+            RETURN_IF_BINDER_EXCEPTION(libInterface->createEffectFunc(&effectSp));
+            if (!effectSp) {
+                LOG(ERROR) << __func__ << ": library created null instance without return error!";
+                return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+            }
+            *_aidl_return = effectSp;
+            mEffectUuidMap[std::weak_ptr<IEffect>(effectSp)] = in_impl_uuid;
+            LOG(DEBUG) << __func__ << ": instance " << effectSp.get() << " created successfully";
+            return ndk::ScopedAStatus::ok();
+        } else {
+            LOG(ERROR) << __func__ << ": library doesn't exist";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+    } else {
+        LOG(ERROR) << __func__ << ": UUID not supported";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Factory::destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle) {
+    std::weak_ptr<IEffect> wpHandle(in_handle);
+    // find UUID with key (std::weak_ptr<IEffect>)
+    if (auto uuidIt = mEffectUuidMap.find(wpHandle); uuidIt != mEffectUuidMap.end()) {
+        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));
+            }
+        } else {
+            LOG(ERROR) << __func__ << ": UUID " << uuid.toString() << " does not exist in libMap!";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+        mEffectUuidMap.erase(uuidIt);
+        return ndk::ScopedAStatus::ok();
+    } else {
+        LOG(ERROR) << __func__ << ": instance " << in_handle << " does not exist!";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+}
+
+// go over the map and cleanup all expired weak_ptrs.
+void Factory::cleanupEffectMap() {
+    for (auto it = mEffectUuidMap.begin(); it != mEffectUuidMap.end();) {
+        if (nullptr == it->first.lock()) {
+            it = mEffectUuidMap.erase(it);
+        } else {
+            ++it;
+        }
+    }
+}
+
+ndk::ScopedAStatus Factory::destroyEffect(const std::shared_ptr<IEffect>& in_handle) {
+    LOG(DEBUG) << __func__ << ": instance " << in_handle.get();
+    ndk::ScopedAStatus status = destroyEffectImpl(in_handle);
+    // always do the cleanup
+    cleanupEffectMap();
+    return status;
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/EffectMain.cpp b/audio/aidl/default/EffectMain.cpp
new file mode 100644
index 0000000..3219dd6
--- /dev/null
+++ b/audio/aidl/default/EffectMain.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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 "effectFactory-impl/EffectFactory.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+int main() {
+    // This is a debug implementation, always enable debug logging.
+    android::base::SetMinimumLogSeverity(::android::base::DEBUG);
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+    auto effectFactory =
+            ndk::SharedRefBase::make<aidl::android::hardware::audio::effect::Factory>();
+
+    std::string serviceName = std::string() + effectFactory->descriptor + "/default";
+    binder_status_t status =
+            AServiceManager_addService(effectFactory->asBinder().get(), serviceName.c_str());
+    CHECK_EQ(STATUS_OK, status);
+    LOG(DEBUG) << __func__ << ": effectFactoryName:" << serviceName;
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reach
+}
diff --git a/audio/aidl/default/EffectThread.cpp b/audio/aidl/default/EffectThread.cpp
new file mode 100644
index 0000000..80f120b
--- /dev/null
+++ b/audio/aidl/default/EffectThread.cpp
@@ -0,0 +1,120 @@
+/*
+ * 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 "AHAL_EffectThread"
+#include <android-base/logging.h>
+#include <pthread.h>
+#include <sys/resource.h>
+
+#include "effect-impl/EffectThread.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+EffectThread::EffectThread() {
+    LOG(DEBUG) << __func__;
+}
+
+EffectThread::~EffectThread() {
+    destroyThread();
+    LOG(DEBUG) << __func__ << " done";
+};
+
+RetCode EffectThread::createThread(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;
+    mThread = std::thread(&EffectThread::threadLoop, this);
+    LOG(DEBUG) << __func__ << " " << name << " priority " << mPriority << " done";
+    return RetCode::SUCCESS;
+}
+
+RetCode EffectThread::destroyThread() {
+    {
+        std::lock_guard lg(mMutex);
+        mStop = mExit = true;
+    }
+    mCv.notify_one();
+
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+    LOG(DEBUG) << __func__ << " done";
+    return RetCode::SUCCESS;
+}
+
+RetCode EffectThread::startThread() {
+    if (!mThread.joinable()) {
+        LOG(ERROR) << __func__ << " thread already destroyed";
+        return RetCode::ERROR_THREAD;
+    }
+
+    {
+        std::lock_guard lg(mMutex);
+        if (!mStop) {
+            LOG(WARNING) << __func__ << " already start";
+            return RetCode::SUCCESS;
+        }
+        mStop = false;
+    }
+
+    mCv.notify_one();
+    LOG(DEBUG) << __func__ << " done";
+    return RetCode::SUCCESS;
+}
+
+RetCode EffectThread::stopThread() {
+    if (!mThread.joinable()) {
+        LOG(ERROR) << __func__ << " thread already destroyed";
+        return RetCode::ERROR_THREAD;
+    }
+
+    {
+        std::lock_guard lg(mMutex);
+        if (mStop) {
+            LOG(WARNING) << __func__ << " already stop";
+            return RetCode::SUCCESS;
+        }
+        mStop = true;
+    }
+    LOG(DEBUG) << __func__ << " done";
+    return RetCode::SUCCESS;
+}
+
+void EffectThread::threadLoop() {
+    pthread_setname_np(pthread_self(), mName.substr(0, MAX_TASK_COMM_LEN - 1).c_str());
+    setpriority(PRIO_PROCESS, 0, mPriority);
+    while (true) {
+        bool needExit = false;
+        {
+            std::unique_lock l(mMutex);
+            mCv.wait(l, [&]() REQUIRES(mMutex) {
+                needExit = mExit;
+                return mExit || !mStop;
+            });
+        }
+        if (needExit) {
+            LOG(WARNING) << __func__ << " EXIT!";
+            return;
+        }
+        // process without lock
+        process();
+    }
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
new file mode 100644
index 0000000..deaca49
--- /dev/null
+++ b/audio/aidl/default/Module.cpp
@@ -0,0 +1,782 @@
+/*
+ * 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 <algorithm>
+#include <set>
+
+#define LOG_TAG "AHAL_Module"
+#include <android-base/logging.h>
+
+#include <Utils.h>
+#include <aidl/android/media/audio/common/AudioInputFlags.h>
+#include <aidl/android/media/audio/common/AudioOutputFlags.h>
+
+#include "core-impl/Module.h"
+#include "core-impl/utils.h"
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioInputFlags;
+using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::AudioOutputFlags;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioProfile;
+using aidl::android::media::audio::common::Int;
+using aidl::android::media::audio::common::PcmType;
+using android::hardware::audio::common::getFrameSizeInBytes;
+using android::hardware::audio::common::isBitPositionFlagSet;
+
+namespace aidl::android::hardware::audio::core {
+
+namespace {
+
+bool generateDefaultPortConfig(const AudioPort& port, AudioPortConfig* config) {
+    *config = {};
+    config->portId = port.id;
+    if (port.profiles.empty()) {
+        LOG(ERROR) << __func__ << ": port " << port.id << " has no profiles";
+        return false;
+    }
+    const auto& profile = port.profiles.begin();
+    config->format = profile->format;
+    if (profile->channelMasks.empty()) {
+        LOG(ERROR) << __func__ << ": the first profile in port " << port.id
+                   << " has no channel masks";
+        return false;
+    }
+    config->channelMask = *profile->channelMasks.begin();
+    if (profile->sampleRates.empty()) {
+        LOG(ERROR) << __func__ << ": the first profile in port " << port.id
+                   << " has no sample rates";
+        return false;
+    }
+    Int sampleRate;
+    sampleRate.value = *profile->sampleRates.begin();
+    config->sampleRate = sampleRate;
+    config->flags = port.flags;
+    config->ext = port.ext;
+    return true;
+}
+
+bool findAudioProfile(const AudioPort& port, const AudioFormatDescription& format,
+                      AudioProfile* profile) {
+    if (auto profilesIt =
+                find_if(port.profiles.begin(), port.profiles.end(),
+                        [&format](const auto& profile) { return profile.format == format; });
+        profilesIt != port.profiles.end()) {
+        *profile = *profilesIt;
+        return true;
+    }
+    return false;
+}
+
+}  // namespace
+
+void Module::cleanUpPatch(int32_t patchId) {
+    erase_all_values(mPatches, std::set<int32_t>{patchId});
+}
+
+ndk::ScopedAStatus Module::createStreamContext(int32_t in_portConfigId, int64_t in_bufferSizeFrames,
+                                               StreamContext* out_context) {
+    if (in_bufferSizeFrames <= 0) {
+        LOG(ERROR) << __func__ << ": non-positive buffer size " << in_bufferSizeFrames;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (in_bufferSizeFrames < kMinimumStreamBufferSizeFrames) {
+        LOG(ERROR) << __func__ << ": insufficient buffer size " << in_bufferSizeFrames
+                   << ", must be at least " << kMinimumStreamBufferSizeFrames;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    auto& configs = getConfig().portConfigs;
+    auto portConfigIt = findById<AudioPortConfig>(configs, in_portConfigId);
+    // Since this is a private method, it is assumed that
+    // validity of the portConfigId has already been checked.
+    const size_t frameSize =
+            getFrameSizeInBytes(portConfigIt->format.value(), portConfigIt->channelMask.value());
+    if (frameSize == 0) {
+        LOG(ERROR) << __func__ << ": could not calculate frame size for port config "
+                   << portConfigIt->toString();
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    LOG(DEBUG) << __func__ << ": frame size " << frameSize << " bytes";
+    if (frameSize > kMaximumStreamBufferSizeBytes / in_bufferSizeFrames) {
+        LOG(ERROR) << __func__ << ": buffer size " << in_bufferSizeFrames
+                   << " frames is too large, maximum size is "
+                   << kMaximumStreamBufferSizeBytes / frameSize;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    const auto& flags = portConfigIt->flags.value();
+    if ((flags.getTag() == AudioIoFlags::Tag::input &&
+         !isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::input>(),
+                               AudioInputFlags::MMAP_NOIRQ)) ||
+        (flags.getTag() == AudioIoFlags::Tag::output &&
+         !isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::output>(),
+                               AudioOutputFlags::MMAP_NOIRQ))) {
+        StreamContext temp(
+                std::make_unique<StreamContext::CommandMQ>(1, true /*configureEventFlagWord*/),
+                std::make_unique<StreamContext::ReplyMQ>(1, true /*configureEventFlagWord*/),
+                frameSize,
+                std::make_unique<StreamContext::DataMQ>(frameSize * in_bufferSizeFrames));
+        if (temp.isValid()) {
+            *out_context = std::move(temp);
+        } else {
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        }
+    } else {
+        // TODO: Implement simulation of MMAP buffer allocation
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::findPortIdForNewStream(int32_t in_portConfigId, AudioPort** port) {
+    auto& configs = getConfig().portConfigs;
+    auto portConfigIt = findById<AudioPortConfig>(configs, in_portConfigId);
+    if (portConfigIt == configs.end()) {
+        LOG(ERROR) << __func__ << ": existing port config id " << in_portConfigId << " not found";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    const int32_t portId = portConfigIt->portId;
+    // In our implementation, configs of mix ports always have unique IDs.
+    CHECK(portId != in_portConfigId);
+    auto& ports = getConfig().ports;
+    auto portIt = findById<AudioPort>(ports, portId);
+    if (portIt == ports.end()) {
+        LOG(ERROR) << __func__ << ": port id " << portId << " used by port config id "
+                   << in_portConfigId << " not found";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (mStreams.count(in_portConfigId) != 0) {
+        LOG(ERROR) << __func__ << ": port config id " << in_portConfigId
+                   << " already has a stream opened on it";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    if (portIt->ext.getTag() != AudioPortExt::Tag::mix) {
+        LOG(ERROR) << __func__ << ": port config id " << in_portConfigId
+                   << " does not correspond to a mix port";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    const int32_t maxOpenStreamCount = portIt->ext.get<AudioPortExt::Tag::mix>().maxOpenStreamCount;
+    if (maxOpenStreamCount != 0 && mStreams.count(portId) >= maxOpenStreamCount) {
+        LOG(ERROR) << __func__ << ": port id " << portId
+                   << " has already reached maximum allowed opened stream count: "
+                   << maxOpenStreamCount;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    *port = &(*portIt);
+    return ndk::ScopedAStatus::ok();
+}
+
+internal::Configuration& Module::getConfig() {
+    if (!mConfig) {
+        mConfig.reset(new internal::Configuration(internal::getNullPrimaryConfiguration()));
+    }
+    return *mConfig;
+}
+
+void Module::registerPatch(const AudioPatch& patch) {
+    auto& configs = getConfig().portConfigs;
+    auto do_insert = [&](const std::vector<int32_t>& portConfigIds) {
+        for (auto portConfigId : portConfigIds) {
+            auto configIt = findById<AudioPortConfig>(configs, portConfigId);
+            if (configIt != configs.end()) {
+                mPatches.insert(std::pair{portConfigId, patch.id});
+                if (configIt->portId != portConfigId) {
+                    mPatches.insert(std::pair{configIt->portId, patch.id});
+                }
+            }
+        };
+    };
+    do_insert(patch.sourcePortConfigIds);
+    do_insert(patch.sinkPortConfigIds);
+}
+
+void Module::updateStreamsConnectedState(const AudioPatch& oldPatch, const AudioPatch& newPatch) {
+    // Streams from the old patch need to be disconnected, streams from the new
+    // patch need to be connected. If the stream belongs to both patches, no need
+    // to update it.
+    std::set<int32_t> idsToDisconnect, idsToConnect;
+    idsToDisconnect.insert(oldPatch.sourcePortConfigIds.begin(),
+                           oldPatch.sourcePortConfigIds.end());
+    idsToDisconnect.insert(oldPatch.sinkPortConfigIds.begin(), oldPatch.sinkPortConfigIds.end());
+    idsToConnect.insert(newPatch.sourcePortConfigIds.begin(), newPatch.sourcePortConfigIds.end());
+    idsToConnect.insert(newPatch.sinkPortConfigIds.begin(), newPatch.sinkPortConfigIds.end());
+    std::for_each(idsToDisconnect.begin(), idsToDisconnect.end(), [&](const auto& portConfigId) {
+        if (idsToConnect.count(portConfigId) == 0) {
+            mStreams.setStreamIsConnected(portConfigId, false);
+        }
+    });
+    std::for_each(idsToConnect.begin(), idsToConnect.end(), [&](const auto& portConfigId) {
+        if (idsToDisconnect.count(portConfigId) == 0) {
+            mStreams.setStreamIsConnected(portConfigId, true);
+        }
+    });
+}
+
+ndk::ScopedAStatus Module::setModuleDebug(
+        const ::aidl::android::hardware::audio::core::ModuleDebug& in_debug) {
+    LOG(DEBUG) << __func__ << ": old flags:" << mDebug.toString()
+               << ", new flags: " << in_debug.toString();
+    if (mDebug.simulateDeviceConnections != in_debug.simulateDeviceConnections &&
+        !mConnectedDevicePorts.empty()) {
+        LOG(ERROR) << __func__ << ": attempting to change device connections simulation "
+                   << "while having external devices connected";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    mDebug = in_debug;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::connectExternalDevice(const AudioPort& in_templateIdAndAdditionalData,
+                                                 AudioPort* _aidl_return) {
+    const int32_t templateId = in_templateIdAndAdditionalData.id;
+    auto& ports = getConfig().ports;
+    AudioPort connectedPort;
+    {  // Scope the template port so that we don't accidentally modify it.
+        auto templateIt = findById<AudioPort>(ports, templateId);
+        if (templateIt == ports.end()) {
+            LOG(ERROR) << __func__ << ": port id " << templateId << " not found";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+        if (templateIt->ext.getTag() != AudioPortExt::Tag::device) {
+            LOG(ERROR) << __func__ << ": port id " << templateId << " is not a device port";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+        if (!templateIt->profiles.empty()) {
+            LOG(ERROR) << __func__ << ": port id " << templateId
+                       << " does not have dynamic profiles";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+        auto& templateDevicePort = templateIt->ext.get<AudioPortExt::Tag::device>();
+        if (templateDevicePort.device.type.connection.empty()) {
+            LOG(ERROR) << __func__ << ": port id " << templateId << " is permanently attached";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+        // Postpone id allocation until we ensure that there are no client errors.
+        connectedPort = *templateIt;
+        connectedPort.extraAudioDescriptors = in_templateIdAndAdditionalData.extraAudioDescriptors;
+        const auto& inputDevicePort =
+                in_templateIdAndAdditionalData.ext.get<AudioPortExt::Tag::device>();
+        auto& connectedDevicePort = connectedPort.ext.get<AudioPortExt::Tag::device>();
+        connectedDevicePort.device.address = inputDevicePort.device.address;
+        LOG(DEBUG) << __func__ << ": device port " << connectedPort.id << " device set to "
+                   << connectedDevicePort.device.toString();
+        // Check if there is already a connected port with for the same external device.
+        for (auto connectedPortId : mConnectedDevicePorts) {
+            auto connectedPortIt = findById<AudioPort>(ports, connectedPortId);
+            if (connectedPortIt->ext.get<AudioPortExt::Tag::device>().device ==
+                connectedDevicePort.device) {
+                LOG(ERROR) << __func__ << ": device " << connectedDevicePort.device.toString()
+                           << " is already connected at the device port id " << connectedPortId;
+                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+            }
+        }
+    }
+
+    if (!mDebug.simulateDeviceConnections) {
+        // In a real HAL here we would attempt querying the profiles from the device.
+        LOG(ERROR) << __func__ << ": failed to query supported device profiles";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+
+    connectedPort.id = ++getConfig().nextPortId;
+    mConnectedDevicePorts.insert(connectedPort.id);
+    LOG(DEBUG) << __func__ << ": template port " << templateId << " external device connected, "
+               << "connected port ID " << connectedPort.id;
+    auto& connectedProfiles = getConfig().connectedProfiles;
+    if (auto connectedProfilesIt = connectedProfiles.find(templateId);
+        connectedProfilesIt != connectedProfiles.end()) {
+        connectedPort.profiles = connectedProfilesIt->second;
+    }
+    ports.push_back(connectedPort);
+    *_aidl_return = std::move(connectedPort);
+
+    std::vector<AudioRoute> newRoutes;
+    auto& routes = getConfig().routes;
+    for (auto& r : routes) {
+        if (r.sinkPortId == templateId) {
+            AudioRoute newRoute;
+            newRoute.sourcePortIds = r.sourcePortIds;
+            newRoute.sinkPortId = connectedPort.id;
+            newRoute.isExclusive = r.isExclusive;
+            newRoutes.push_back(std::move(newRoute));
+        } else {
+            auto& srcs = r.sourcePortIds;
+            if (std::find(srcs.begin(), srcs.end(), templateId) != srcs.end()) {
+                srcs.push_back(connectedPort.id);
+            }
+        }
+    }
+    routes.insert(routes.end(), newRoutes.begin(), newRoutes.end());
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::disconnectExternalDevice(int32_t in_portId) {
+    auto& ports = getConfig().ports;
+    auto portIt = findById<AudioPort>(ports, in_portId);
+    if (portIt == ports.end()) {
+        LOG(ERROR) << __func__ << ": port id " << in_portId << " not found";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (portIt->ext.getTag() != AudioPortExt::Tag::device) {
+        LOG(ERROR) << __func__ << ": port id " << in_portId << " is not a device port";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (mConnectedDevicePorts.count(in_portId) == 0) {
+        LOG(ERROR) << __func__ << ": port id " << in_portId << " is not a connected device port";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    auto& configs = getConfig().portConfigs;
+    auto& initials = getConfig().initialConfigs;
+    auto configIt = std::find_if(configs.begin(), configs.end(), [&](const auto& config) {
+        if (config.portId == in_portId) {
+            // Check if the configuration was provided by the client.
+            const auto& initialIt = findById<AudioPortConfig>(initials, config.id);
+            return initialIt == initials.end() || config != *initialIt;
+        }
+        return false;
+    });
+    if (configIt != configs.end()) {
+        LOG(ERROR) << __func__ << ": port id " << in_portId << " has a non-default config with id "
+                   << configIt->id;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    ports.erase(portIt);
+    mConnectedDevicePorts.erase(in_portId);
+    LOG(DEBUG) << __func__ << ": connected device port " << in_portId << " released";
+
+    auto& routes = getConfig().routes;
+    for (auto routesIt = routes.begin(); routesIt != routes.end();) {
+        if (routesIt->sinkPortId == in_portId) {
+            routesIt = routes.erase(routesIt);
+        } else {
+            // Note: the list of sourcePortIds can't become empty because there must
+            // be the id of the template port in the route.
+            erase_if(routesIt->sourcePortIds, [in_portId](auto src) { return src == in_portId; });
+            ++routesIt;
+        }
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::getAudioPatches(std::vector<AudioPatch>* _aidl_return) {
+    *_aidl_return = getConfig().patches;
+    LOG(DEBUG) << __func__ << ": returning " << _aidl_return->size() << " patches";
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::getAudioPort(int32_t in_portId, AudioPort* _aidl_return) {
+    auto& ports = getConfig().ports;
+    auto portIt = findById<AudioPort>(ports, in_portId);
+    if (portIt != ports.end()) {
+        *_aidl_return = *portIt;
+        LOG(DEBUG) << __func__ << ": returning port by id " << in_portId;
+        return ndk::ScopedAStatus::ok();
+    }
+    LOG(ERROR) << __func__ << ": port id " << in_portId << " not found";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
+ndk::ScopedAStatus Module::getAudioPortConfigs(std::vector<AudioPortConfig>* _aidl_return) {
+    *_aidl_return = getConfig().portConfigs;
+    LOG(DEBUG) << __func__ << ": returning " << _aidl_return->size() << " port configs";
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::getAudioPorts(std::vector<AudioPort>* _aidl_return) {
+    *_aidl_return = getConfig().ports;
+    LOG(DEBUG) << __func__ << ": returning " << _aidl_return->size() << " ports";
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::getAudioRoutes(std::vector<AudioRoute>* _aidl_return) {
+    *_aidl_return = getConfig().routes;
+    LOG(DEBUG) << __func__ << ": returning " << _aidl_return->size() << " routes";
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::getAudioRoutesForAudioPort(int32_t in_portId,
+                                                      std::vector<AudioRoute>* _aidl_return) {
+    auto& ports = getConfig().ports;
+    if (auto portIt = findById<AudioPort>(ports, in_portId); portIt == ports.end()) {
+        LOG(ERROR) << __func__ << ": port id " << in_portId << " not found";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    auto& routes = getConfig().routes;
+    std::copy_if(routes.begin(), routes.end(), std::back_inserter(*_aidl_return),
+                 [&](const auto& r) {
+                     const auto& srcs = r.sourcePortIds;
+                     return r.sinkPortId == in_portId ||
+                            std::find(srcs.begin(), srcs.end(), in_portId) != srcs.end();
+                 });
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::openInputStream(const OpenInputStreamArguments& in_args,
+                                           OpenInputStreamReturn* _aidl_return) {
+    LOG(DEBUG) << __func__ << ": port config id " << in_args.portConfigId << ", buffer size "
+               << in_args.bufferSizeFrames << " frames";
+    AudioPort* port = nullptr;
+    if (auto status = findPortIdForNewStream(in_args.portConfigId, &port); !status.isOk()) {
+        return status;
+    }
+    if (port->flags.getTag() != AudioIoFlags::Tag::input) {
+        LOG(ERROR) << __func__ << ": port config id " << in_args.portConfigId
+                   << " does not correspond to an input mix port";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    StreamContext context;
+    if (auto status = createStreamContext(in_args.portConfigId, in_args.bufferSizeFrames, &context);
+        !status.isOk()) {
+        return status;
+    }
+    context.fillDescriptor(&_aidl_return->desc);
+    auto stream = ndk::SharedRefBase::make<StreamIn>(in_args.sinkMetadata, std::move(context));
+    if (auto status = stream->init(); !status.isOk()) {
+        return status;
+    }
+    StreamWrapper streamWrapper(stream);
+    auto patchIt = mPatches.find(in_args.portConfigId);
+    if (patchIt != mPatches.end()) {
+        streamWrapper.setStreamIsConnected(true);
+    }
+    mStreams.insert(port->id, in_args.portConfigId, std::move(streamWrapper));
+    _aidl_return->stream = std::move(stream);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::openOutputStream(const OpenOutputStreamArguments& in_args,
+                                            OpenOutputStreamReturn* _aidl_return) {
+    LOG(DEBUG) << __func__ << ": port config id " << in_args.portConfigId << ", has offload info? "
+               << (in_args.offloadInfo.has_value()) << ", buffer size " << in_args.bufferSizeFrames
+               << " frames";
+    AudioPort* port = nullptr;
+    if (auto status = findPortIdForNewStream(in_args.portConfigId, &port); !status.isOk()) {
+        return status;
+    }
+    if (port->flags.getTag() != AudioIoFlags::Tag::output) {
+        LOG(ERROR) << __func__ << ": port config id " << in_args.portConfigId
+                   << " does not correspond to an output mix port";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    const bool isOffload = isBitPositionFlagSet(port->flags.get<AudioIoFlags::Tag::output>(),
+                                                AudioOutputFlags::COMPRESS_OFFLOAD);
+    if (isOffload && !in_args.offloadInfo.has_value()) {
+        LOG(ERROR) << __func__ << ": port id " << port->id
+                   << " has COMPRESS_OFFLOAD flag set, requires offload info";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    StreamContext context;
+    if (auto status = createStreamContext(in_args.portConfigId, in_args.bufferSizeFrames, &context);
+        !status.isOk()) {
+        return status;
+    }
+    context.fillDescriptor(&_aidl_return->desc);
+    auto stream = ndk::SharedRefBase::make<StreamOut>(in_args.sourceMetadata, std::move(context),
+                                                      in_args.offloadInfo);
+    if (auto status = stream->init(); !status.isOk()) {
+        return status;
+    }
+    StreamWrapper streamWrapper(stream);
+    auto patchIt = mPatches.find(in_args.portConfigId);
+    if (patchIt != mPatches.end()) {
+        streamWrapper.setStreamIsConnected(true);
+    }
+    mStreams.insert(port->id, in_args.portConfigId, std::move(streamWrapper));
+    _aidl_return->stream = std::move(stream);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::setAudioPatch(const AudioPatch& in_requested, AudioPatch* _aidl_return) {
+    LOG(DEBUG) << __func__ << ": requested patch " << in_requested.toString();
+    if (in_requested.sourcePortConfigIds.empty()) {
+        LOG(ERROR) << __func__ << ": requested patch has empty sources list";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (!all_unique<int32_t>(in_requested.sourcePortConfigIds)) {
+        LOG(ERROR) << __func__ << ": requested patch has duplicate ids in the sources list";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (in_requested.sinkPortConfigIds.empty()) {
+        LOG(ERROR) << __func__ << ": requested patch has empty sinks list";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (!all_unique<int32_t>(in_requested.sinkPortConfigIds)) {
+        LOG(ERROR) << __func__ << ": requested patch has duplicate ids in the sinks list";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+
+    auto& configs = getConfig().portConfigs;
+    std::vector<int32_t> missingIds;
+    auto sources =
+            selectByIds<AudioPortConfig>(configs, in_requested.sourcePortConfigIds, &missingIds);
+    if (!missingIds.empty()) {
+        LOG(ERROR) << __func__ << ": following source port config ids not found: "
+                   << ::android::internal::ToString(missingIds);
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    auto sinks = selectByIds<AudioPortConfig>(configs, in_requested.sinkPortConfigIds, &missingIds);
+    if (!missingIds.empty()) {
+        LOG(ERROR) << __func__ << ": following sink port config ids not found: "
+                   << ::android::internal::ToString(missingIds);
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    // bool indicates whether a non-exclusive route is available.
+    // If only an exclusive route is available, that means the patch can not be
+    // established if there is any other patch which currently uses the sink port.
+    std::map<int32_t, bool> allowedSinkPorts;
+    auto& routes = getConfig().routes;
+    for (auto src : sources) {
+        for (const auto& r : routes) {
+            const auto& srcs = r.sourcePortIds;
+            if (std::find(srcs.begin(), srcs.end(), src->portId) != srcs.end()) {
+                if (!allowedSinkPorts[r.sinkPortId]) {  // prefer non-exclusive
+                    allowedSinkPorts[r.sinkPortId] = !r.isExclusive;
+                }
+            }
+        }
+    }
+    for (auto sink : sinks) {
+        if (allowedSinkPorts.count(sink->portId) == 0) {
+            LOG(ERROR) << __func__ << ": there is no route to the sink port id " << sink->portId;
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+    }
+
+    auto& patches = getConfig().patches;
+    auto existing = patches.end();
+    std::optional<decltype(mPatches)> patchesBackup;
+    if (in_requested.id != 0) {
+        existing = findById<AudioPatch>(patches, in_requested.id);
+        if (existing != patches.end()) {
+            patchesBackup = mPatches;
+            cleanUpPatch(existing->id);
+        } else {
+            LOG(ERROR) << __func__ << ": not found existing patch id " << in_requested.id;
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+    }
+    // Validate the requested patch.
+    for (const auto& [sinkPortId, nonExclusive] : allowedSinkPorts) {
+        if (!nonExclusive && mPatches.count(sinkPortId) != 0) {
+            LOG(ERROR) << __func__ << ": sink port id " << sinkPortId
+                       << "is exclusive and is already used by some other patch";
+            if (patchesBackup.has_value()) {
+                mPatches = std::move(*patchesBackup);
+            }
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        }
+    }
+    *_aidl_return = in_requested;
+    _aidl_return->minimumStreamBufferSizeFrames = kMinimumStreamBufferSizeFrames;
+    _aidl_return->latenciesMs.clear();
+    _aidl_return->latenciesMs.insert(_aidl_return->latenciesMs.end(),
+                                     _aidl_return->sinkPortConfigIds.size(), kLatencyMs);
+    AudioPatch oldPatch{};
+    if (existing == patches.end()) {
+        _aidl_return->id = getConfig().nextPatchId++;
+        patches.push_back(*_aidl_return);
+        existing = patches.begin() + (patches.size() - 1);
+    } else {
+        oldPatch = *existing;
+        *existing = *_aidl_return;
+    }
+    registerPatch(*existing);
+    updateStreamsConnectedState(oldPatch, *_aidl_return);
+
+    LOG(DEBUG) << __func__ << ": " << (oldPatch.id == 0 ? "created" : "updated") << " patch "
+               << _aidl_return->toString();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::setAudioPortConfig(const AudioPortConfig& in_requested,
+                                              AudioPortConfig* out_suggested, bool* _aidl_return) {
+    LOG(DEBUG) << __func__ << ": requested " << in_requested.toString();
+    auto& configs = getConfig().portConfigs;
+    auto existing = configs.end();
+    if (in_requested.id != 0) {
+        if (existing = findById<AudioPortConfig>(configs, in_requested.id);
+            existing == configs.end()) {
+            LOG(ERROR) << __func__ << ": existing port config id " << in_requested.id
+                       << " not found";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+    }
+
+    const int portId = existing != configs.end() ? existing->portId : in_requested.portId;
+    if (portId == 0) {
+        LOG(ERROR) << __func__ << ": input port config does not specify portId";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    auto& ports = getConfig().ports;
+    auto portIt = findById<AudioPort>(ports, portId);
+    if (portIt == ports.end()) {
+        LOG(ERROR) << __func__ << ": input port config points to non-existent portId " << portId;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (existing != configs.end()) {
+        *out_suggested = *existing;
+    } else {
+        AudioPortConfig newConfig;
+        if (generateDefaultPortConfig(*portIt, &newConfig)) {
+            *out_suggested = newConfig;
+        } else {
+            LOG(ERROR) << __func__ << ": unable generate a default config for port " << portId;
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+    }
+    // From this moment, 'out_suggested' is either an existing port config,
+    // or a new generated config. Now attempt to update it according to the specified
+    // fields of 'in_requested'.
+
+    bool requestedIsValid = true, requestedIsFullySpecified = true;
+
+    AudioIoFlags portFlags = portIt->flags;
+    if (in_requested.flags.has_value()) {
+        if (in_requested.flags.value() != portFlags) {
+            LOG(WARNING) << __func__ << ": requested flags "
+                         << in_requested.flags.value().toString() << " do not match port's "
+                         << portId << " flags " << portFlags.toString();
+            requestedIsValid = false;
+        }
+    } else {
+        requestedIsFullySpecified = false;
+    }
+
+    AudioProfile portProfile;
+    if (in_requested.format.has_value()) {
+        const auto& format = in_requested.format.value();
+        if (findAudioProfile(*portIt, format, &portProfile)) {
+            out_suggested->format = format;
+        } else {
+            LOG(WARNING) << __func__ << ": requested format " << format.toString()
+                         << " is not found in port's " << portId << " profiles";
+            requestedIsValid = false;
+        }
+    } else {
+        requestedIsFullySpecified = false;
+    }
+    if (!findAudioProfile(*portIt, out_suggested->format.value(), &portProfile)) {
+        LOG(ERROR) << __func__ << ": port " << portId << " does not support format "
+                   << out_suggested->format.value().toString() << " anymore";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+
+    if (in_requested.channelMask.has_value()) {
+        const auto& channelMask = in_requested.channelMask.value();
+        if (find(portProfile.channelMasks.begin(), portProfile.channelMasks.end(), channelMask) !=
+            portProfile.channelMasks.end()) {
+            out_suggested->channelMask = channelMask;
+        } else {
+            LOG(WARNING) << __func__ << ": requested channel mask " << channelMask.toString()
+                         << " is not supported for the format " << portProfile.format.toString()
+                         << " by the port " << portId;
+            requestedIsValid = false;
+        }
+    } else {
+        requestedIsFullySpecified = false;
+    }
+
+    if (in_requested.sampleRate.has_value()) {
+        const auto& sampleRate = in_requested.sampleRate.value();
+        if (find(portProfile.sampleRates.begin(), portProfile.sampleRates.end(),
+                 sampleRate.value) != portProfile.sampleRates.end()) {
+            out_suggested->sampleRate = sampleRate;
+        } else {
+            LOG(WARNING) << __func__ << ": requested sample rate " << sampleRate.value
+                         << " is not supported for the format " << portProfile.format.toString()
+                         << " by the port " << portId;
+            requestedIsValid = false;
+        }
+    } else {
+        requestedIsFullySpecified = false;
+    }
+
+    if (in_requested.gain.has_value()) {
+        // Let's pretend that gain can always be applied.
+        out_suggested->gain = in_requested.gain.value();
+    }
+
+    if (existing == configs.end() && requestedIsValid && requestedIsFullySpecified) {
+        out_suggested->id = getConfig().nextPortId++;
+        configs.push_back(*out_suggested);
+        *_aidl_return = true;
+        LOG(DEBUG) << __func__ << ": created new port config " << out_suggested->toString();
+    } else if (existing != configs.end() && requestedIsValid) {
+        *existing = *out_suggested;
+        *_aidl_return = true;
+        LOG(DEBUG) << __func__ << ": updated port config " << out_suggested->toString();
+    } else {
+        LOG(DEBUG) << __func__ << ": not applied; existing config ? " << (existing != configs.end())
+                   << "; requested is valid? " << requestedIsValid << ", fully specified? "
+                   << requestedIsFullySpecified;
+        *_aidl_return = false;
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::resetAudioPatch(int32_t in_patchId) {
+    auto& patches = getConfig().patches;
+    auto patchIt = findById<AudioPatch>(patches, in_patchId);
+    if (patchIt != patches.end()) {
+        cleanUpPatch(patchIt->id);
+        updateStreamsConnectedState(*patchIt, AudioPatch{});
+        patches.erase(patchIt);
+        LOG(DEBUG) << __func__ << ": erased patch " << in_patchId;
+        return ndk::ScopedAStatus::ok();
+    }
+    LOG(ERROR) << __func__ << ": patch id " << in_patchId << " not found";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
+ndk::ScopedAStatus Module::resetAudioPortConfig(int32_t in_portConfigId) {
+    auto& configs = getConfig().portConfigs;
+    auto configIt = findById<AudioPortConfig>(configs, in_portConfigId);
+    if (configIt != configs.end()) {
+        if (mStreams.count(in_portConfigId) != 0) {
+            LOG(ERROR) << __func__ << ": port config id " << in_portConfigId
+                       << " has a stream opened on it";
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        }
+        auto patchIt = mPatches.find(in_portConfigId);
+        if (patchIt != mPatches.end()) {
+            LOG(ERROR) << __func__ << ": port config id " << in_portConfigId
+                       << " is used by the patch with id " << patchIt->second;
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        }
+        auto& initials = getConfig().initialConfigs;
+        auto initialIt = findById<AudioPortConfig>(initials, in_portConfigId);
+        if (initialIt == initials.end()) {
+            configs.erase(configIt);
+            LOG(DEBUG) << __func__ << ": erased port config " << in_portConfigId;
+        } else if (*configIt != *initialIt) {
+            *configIt = *initialIt;
+            LOG(DEBUG) << __func__ << ": reset port config " << in_portConfigId;
+        }
+        return ndk::ScopedAStatus::ok();
+    }
+    LOG(ERROR) << __func__ << ": port config id " << in_portConfigId << " not found";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
new file mode 100644
index 0000000..312df72
--- /dev/null
+++ b/audio/aidl/default/Stream.cpp
@@ -0,0 +1,271 @@
+/*
+ * 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 "AHAL_Stream"
+#include <android-base/logging.h>
+#include <utils/SystemClock.h>
+
+#include "core-impl/Module.h"
+#include "core-impl/Stream.h"
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+
+namespace aidl::android::hardware::audio::core {
+
+void StreamContext::fillDescriptor(StreamDescriptor* desc) {
+    if (mCommandMQ) {
+        desc->command = mCommandMQ->dupeDesc();
+    }
+    if (mReplyMQ) {
+        desc->reply = mReplyMQ->dupeDesc();
+    }
+    if (mDataMQ) {
+        desc->frameSizeBytes = mFrameSize;
+        desc->bufferSizeFrames =
+                mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() / mFrameSize;
+        desc->audio.set<StreamDescriptor::AudioBuffer::Tag::fmq>(mDataMQ->dupeDesc());
+    }
+}
+
+bool StreamContext::isValid() const {
+    if (mCommandMQ && !mCommandMQ->isValid()) {
+        LOG(ERROR) << "command FMQ is invalid";
+        return false;
+    }
+    if (mReplyMQ && !mReplyMQ->isValid()) {
+        LOG(ERROR) << "reply FMQ is invalid";
+        return false;
+    }
+    if (mFrameSize == 0) {
+        LOG(ERROR) << "frame size is not set";
+        return false;
+    }
+    if (mDataMQ && !mDataMQ->isValid()) {
+        LOG(ERROR) << "data FMQ is invalid";
+        return false;
+    }
+    return true;
+}
+
+void StreamContext::reset() {
+    mCommandMQ.reset();
+    mReplyMQ.reset();
+    mDataMQ.reset();
+}
+
+std::string StreamWorkerCommonLogic::init() {
+    if (mCommandMQ == nullptr) return "Command MQ is null";
+    if (mReplyMQ == nullptr) return "Reply MQ is null";
+    if (mDataMQ == nullptr) return "Data MQ is null";
+    if (sizeof(decltype(mDataBuffer)::element_type) != mDataMQ->getQuantumSize()) {
+        return "Unexpected Data MQ quantum size: " + std::to_string(mDataMQ->getQuantumSize());
+    }
+    mDataBufferSize = mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize();
+    mDataBuffer.reset(new (std::nothrow) int8_t[mDataBufferSize]);
+    if (mDataBuffer == nullptr) {
+        return "Failed to allocate data buffer for element count " +
+               std::to_string(mDataMQ->getQuantumCount()) +
+               ", size in bytes: " + std::to_string(mDataBufferSize);
+    }
+    return "";
+}
+
+const std::string StreamInWorkerLogic::kThreadName = "reader";
+
+StreamInWorkerLogic::Status StreamInWorkerLogic::cycle() {
+    StreamDescriptor::Command command{};
+    if (!mCommandMQ->readBlocking(&command, 1)) {
+        LOG(ERROR) << __func__ << ": reading of command from MQ failed";
+        return Status::ABORT;
+    }
+    StreamDescriptor::Reply reply{};
+    if (command.code == StreamContext::COMMAND_EXIT &&
+        command.fmqByteCount == mInternalCommandCookie) {
+        LOG(DEBUG) << __func__ << ": received EXIT command";
+        // This is an internal command, no need to reply.
+        return Status::EXIT;
+    } else if (command.code == StreamDescriptor::COMMAND_BURST && command.fmqByteCount >= 0) {
+        LOG(DEBUG) << __func__ << ": received BURST read command for " << command.fmqByteCount
+                   << " bytes";
+        usleep(3000);  // Simulate a blocking call into the driver.
+        const size_t byteCount = std::min({static_cast<size_t>(command.fmqByteCount),
+                                           mDataMQ->availableToWrite(), mDataBufferSize});
+        const bool isConnected = mIsConnected;
+        // Simulate reading of data, or provide zeroes if the stream is not connected.
+        for (size_t i = 0; i < byteCount; ++i) {
+            using buffer_type = decltype(mDataBuffer)::element_type;
+            constexpr int kBufferValueRange = std::numeric_limits<buffer_type>::max() -
+                                              std::numeric_limits<buffer_type>::min() + 1;
+            mDataBuffer[i] = isConnected ? (std::rand() % kBufferValueRange) +
+                                                   std::numeric_limits<buffer_type>::min()
+                                         : 0;
+        }
+        bool success = byteCount > 0 ? mDataMQ->write(&mDataBuffer[0], byteCount) : true;
+        if (success) {
+            LOG(DEBUG) << __func__ << ": writing of " << byteCount << " bytes into data MQ"
+                       << " succeeded; connected? " << isConnected;
+            // Frames are provided and counted regardless of connection status.
+            reply.fmqByteCount = byteCount;
+            mFrameCount += byteCount / mFrameSize;
+            if (isConnected) {
+                reply.status = STATUS_OK;
+                reply.observable.frames = mFrameCount;
+                reply.observable.timeNs = ::android::elapsedRealtimeNano();
+            } else {
+                reply.status = STATUS_INVALID_OPERATION;
+            }
+        } else {
+            LOG(WARNING) << __func__ << ": writing of " << byteCount
+                         << " bytes of data to MQ failed";
+            reply.status = STATUS_NOT_ENOUGH_DATA;
+        }
+        reply.latencyMs = Module::kLatencyMs;
+    } else {
+        LOG(WARNING) << __func__ << ": invalid command (" << command.toString()
+                     << ") or count: " << command.fmqByteCount;
+        reply.status = STATUS_BAD_VALUE;
+    }
+    LOG(DEBUG) << __func__ << ": writing reply " << reply.toString();
+    if (!mReplyMQ->writeBlocking(&reply, 1)) {
+        LOG(ERROR) << __func__ << ": writing of reply " << reply.toString() << " to MQ failed";
+        return Status::ABORT;
+    }
+    return Status::CONTINUE;
+}
+
+const std::string StreamOutWorkerLogic::kThreadName = "writer";
+
+StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
+    StreamDescriptor::Command command{};
+    if (!mCommandMQ->readBlocking(&command, 1)) {
+        LOG(ERROR) << __func__ << ": reading of command from MQ failed";
+        return Status::ABORT;
+    }
+    StreamDescriptor::Reply reply{};
+    if (command.code == StreamContext::COMMAND_EXIT &&
+        command.fmqByteCount == mInternalCommandCookie) {
+        LOG(DEBUG) << __func__ << ": received EXIT command";
+        // This is an internal command, no need to reply.
+        return Status::EXIT;
+    } else if (command.code == StreamDescriptor::COMMAND_BURST && command.fmqByteCount >= 0) {
+        LOG(DEBUG) << __func__ << ": received BURST write command for " << command.fmqByteCount
+                   << " bytes";
+        const size_t byteCount = std::min({static_cast<size_t>(command.fmqByteCount),
+                                           mDataMQ->availableToRead(), mDataBufferSize});
+        bool success = byteCount > 0 ? mDataMQ->read(&mDataBuffer[0], byteCount) : true;
+        if (success) {
+            const bool isConnected = mIsConnected;
+            LOG(DEBUG) << __func__ << ": reading of " << byteCount << " bytes from data MQ"
+                       << " succeeded; connected? " << isConnected;
+            // Frames are consumed and counted regardless of connection status.
+            reply.fmqByteCount = byteCount;
+            mFrameCount += byteCount / mFrameSize;
+            if (isConnected) {
+                reply.status = STATUS_OK;
+                reply.observable.frames = mFrameCount;
+                reply.observable.timeNs = ::android::elapsedRealtimeNano();
+            } else {
+                reply.status = STATUS_INVALID_OPERATION;
+            }
+            usleep(3000);  // Simulate a blocking call into the driver.
+        } else {
+            LOG(WARNING) << __func__ << ": reading of " << byteCount
+                         << " bytes of data from MQ failed";
+            reply.status = STATUS_NOT_ENOUGH_DATA;
+        }
+        reply.latencyMs = Module::kLatencyMs;
+    } else {
+        LOG(WARNING) << __func__ << ": invalid command (" << command.toString()
+                     << ") or count: " << command.fmqByteCount;
+        reply.status = STATUS_BAD_VALUE;
+    }
+    LOG(DEBUG) << __func__ << ": writing reply " << reply.toString();
+    if (!mReplyMQ->writeBlocking(&reply, 1)) {
+        LOG(ERROR) << __func__ << ": writing of reply " << reply.toString() << " to MQ failed";
+        return Status::ABORT;
+    }
+    return Status::CONTINUE;
+}
+
+template <class Metadata, class StreamWorker>
+StreamCommon<Metadata, StreamWorker>::~StreamCommon() {
+    if (!mIsClosed) {
+        LOG(ERROR) << __func__ << ": stream was not closed prior to destruction, resource leak";
+        stopWorker();
+        // The worker and the context should clean up by themselves via destructors.
+    }
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommon<Metadata, StreamWorker>::close() {
+    LOG(DEBUG) << __func__;
+    if (!mIsClosed) {
+        stopWorker();
+        LOG(DEBUG) << __func__ << ": joining the worker thread...";
+        mWorker.stop();
+        LOG(DEBUG) << __func__ << ": worker thread joined";
+        mContext.reset();
+        mIsClosed = true;
+        return ndk::ScopedAStatus::ok();
+    } else {
+        LOG(ERROR) << __func__ << ": stream was already closed";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+}
+
+template <class Metadata, class StreamWorker>
+void StreamCommon<Metadata, StreamWorker>::stopWorker() {
+    if (auto commandMQ = mContext.getCommandMQ(); commandMQ != nullptr) {
+        LOG(DEBUG) << __func__ << ": asking the worker to stop...";
+        StreamDescriptor::Command cmd;
+        cmd.code = StreamContext::COMMAND_EXIT;
+        cmd.fmqByteCount = mContext.getInternalCommandCookie();
+        // FIXME: This can block in the case when the client wrote a command
+        // while the stream worker's cycle is not running. Need to revisit
+        // when implementing standby and pause/resume.
+        if (!commandMQ->writeBlocking(&cmd, 1)) {
+            LOG(ERROR) << __func__ << ": failed to write exit command to the MQ";
+        }
+        LOG(DEBUG) << __func__ << ": done";
+    }
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommon<Metadata, StreamWorker>::updateMetadata(const Metadata& metadata) {
+    LOG(DEBUG) << __func__;
+    if (!mIsClosed) {
+        mMetadata = metadata;
+        return ndk::ScopedAStatus::ok();
+    }
+    LOG(ERROR) << __func__ << ": stream was closed";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+}
+
+StreamIn::StreamIn(const SinkMetadata& sinkMetadata, StreamContext context)
+    : StreamCommon<SinkMetadata, StreamInWorker>(sinkMetadata, std::move(context)) {
+    LOG(DEBUG) << __func__;
+}
+
+StreamOut::StreamOut(const SourceMetadata& sourceMetadata, StreamContext context,
+                     const std::optional<AudioOffloadInfo>& offloadInfo)
+    : StreamCommon<SourceMetadata, StreamOutWorker>(sourceMetadata, std::move(context)),
+      mOffloadInfo(offloadInfo) {
+    LOG(DEBUG) << __func__;
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc b/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc
new file mode 100644
index 0000000..68bbf5b
--- /dev/null
+++ b/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc
@@ -0,0 +1,9 @@
+service vendor.audio-effect-hal-aidl /vendor/bin/hw/android.hardware.audio.effect.service-aidl.example
+    class hal
+    user audioserver
+    # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
+    group audio media
+    capabilities BLOCK_SUSPEND
+    ioprio rt 4
+    task_profiles ProcessCapacityHigh HighPerformance
+    onrestart restart audioserver
diff --git a/audio/aidl/default/android.hardware.audio.effect.service-aidl.xml b/audio/aidl/default/android.hardware.audio.effect.service-aidl.xml
new file mode 100644
index 0000000..fdc53a3
--- /dev/null
+++ b/audio/aidl/default/android.hardware.audio.effect.service-aidl.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+  <hal format="aidl">
+    <name>android.hardware.audio.effect</name>
+    <version>1</version>
+    <fqname>IFactory/default</fqname>
+  </hal>
+</manifest>
diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.example.rc b/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
new file mode 100644
index 0000000..02a9c37
--- /dev/null
+++ b/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
@@ -0,0 +1,9 @@
+service vendor.audio-hal-aidl /vendor/bin/hw/android.hardware.audio.service-aidl.example
+    class hal
+    user audioserver
+    # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
+    group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
+    capabilities BLOCK_SUSPEND
+    ioprio rt 4
+    task_profiles ProcessCapacityHigh HighPerformance
+    onrestart restart audioserver
diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.xml b/audio/aidl/default/android.hardware.audio.service-aidl.xml
new file mode 100644
index 0000000..bb4b01a
--- /dev/null
+++ b/audio/aidl/default/android.hardware.audio.service-aidl.xml
@@ -0,0 +1,12 @@
+<manifest version="1.0" type="device">
+  <hal format="aidl">
+    <name>android.hardware.audio.core</name>
+    <version>1</version>
+    <fqname>IModule/default</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/equalizer/Android.bp b/audio/aidl/default/equalizer/Android.bp
new file mode 100644
index 0000000..2a2ddbc
--- /dev/null
+++ b/audio/aidl/default/equalizer/Android.bp
@@ -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.
+ */
+
+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_shared {
+    name: "libequalizer",
+    vendor: true,
+    shared_libs: [
+        "libaudioaidlcommon",
+        "libbase",
+        "android.hardware.common-V2-ndk",
+    ],
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_media_audio_common_types_ndk_shared",
+        "latest_android_hardware_audio_effect_ndk_shared",
+    ],
+    srcs: [
+        "Equalizer.cpp",
+        ":effectCommonFile",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+    ],
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
+    ],
+}
diff --git a/audio/aidl/default/equalizer/Equalizer.cpp b/audio/aidl/default/equalizer/Equalizer.cpp
new file mode 100644
index 0000000..43fa206
--- /dev/null
+++ b/audio/aidl/default/equalizer/Equalizer.cpp
@@ -0,0 +1,322 @@
+/*
+ * 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 "AHAL_EqualizerSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "equalizer-impl/EqualizerSw.h"
+
+using android::hardware::audio::common::getFrameSizeInBytes;
+
+namespace aidl::android::hardware::audio::effect {
+
+extern "C" binder_exception_t createEffect(std::shared_ptr<IEffect>* instanceSpp) {
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<EqualizerSw>();
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+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;
+}
+
+ndk::ScopedAStatus EqualizerSw::open(const Parameter::Common& common,
+                                     const Parameter::Specific& specific,
+                                     OpenEffectReturn* _aidl_return) {
+    LOG(DEBUG) << __func__;
+    if (mState != State::INIT) {
+        LOG(WARNING) << __func__ << " eq already open";
+        return ndk::ScopedAStatus::ok();
+    }
+
+    // Set essential parameters before create worker thread.
+    setCommonParameter(common);
+    setSpecificParameter(specific);
+
+    LOG(DEBUG) << " common: " << common.toString() << " specific " << specific.toString();
+
+    auto& input = common.input;
+    auto& output = common.output;
+    size_t inputFrameSize = getFrameSizeInBytes(input.base.format, input.base.channelMask);
+    size_t outputFrameSize = getFrameSizeInBytes(output.base.format, output.base.channelMask);
+    mContext = std::make_shared<EqualizerSwContext>(1, input.frameCount * inputFrameSize,
+                                                    output.frameCount * outputFrameSize);
+    if (!mContext) {
+        LOG(ERROR) << __func__ << " created EqualizerSwContext failed";
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION,
+                                                                "FailedToCreateFmq");
+    }
+    setContext(mContext);
+
+    // create the worker thread
+    if (RetCode::SUCCESS != createThread(LOG_TAG)) {
+        LOG(ERROR) << __func__ << " created worker thread failed";
+        mContext.reset();
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION,
+                                                                "FailedToCreateWorker");
+    }
+
+    _aidl_return->statusMQ = mContext->getStatusFmq()->dupeDesc();
+    _aidl_return->inputDataMQ = mContext->getInputDataFmq()->dupeDesc();
+    _aidl_return->outputDataMQ = mContext->getOutputDataFmq()->dupeDesc();
+    mState = State::IDLE;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EqualizerSw::close() {
+    if (mState == State::INIT) {
+        LOG(WARNING) << __func__ << " instance already closed";
+        return ndk::ScopedAStatus::ok();
+    } else if (mState == State::PROCESSING) {
+        LOG(ERROR) << __func__ << " instance still processing";
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
+                                                                "EqInstanceProcessing");
+    }
+
+    // stop the worker thread
+    mState = State::INIT;
+    destroyThread();
+    mContext.reset();
+
+    LOG(DEBUG) << __func__;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EqualizerSw::getDescriptor(Descriptor* _aidl_return) {
+    LOG(DEBUG) << __func__ << mDesc.toString();
+    *_aidl_return = mDesc;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EqualizerSw::command(CommandId in_commandId) {
+    LOG(DEBUG) << __func__ << ": receive command:" << toString(in_commandId);
+    if (mState == State::INIT) {
+        LOG(ERROR) << __func__ << ": instance not open yet";
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
+                                                                "CommandStateError");
+    }
+    switch (in_commandId) {
+        case CommandId::START:
+            // start processing.
+            mState = State::PROCESSING;
+            startThread();
+            LOG(DEBUG) << __func__ << " state: " << toString(mState);
+            return ndk::ScopedAStatus::ok();
+        case CommandId::STOP:
+            // stop processing.
+            mState = State::IDLE;
+            stopThread();
+            LOG(DEBUG) << __func__ << " state: " << toString(mState);
+            return ndk::ScopedAStatus::ok();
+        case CommandId::RESET:
+            // TODO: reset buffer status.
+            mState = State::IDLE;
+            stopThread();
+            LOG(DEBUG) << __func__ << " state: " << toString(mState);
+            return ndk::ScopedAStatus::ok();
+        default:
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "CommandIdNotSupported");
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EqualizerSw::setParameter(const Parameter& in_param) {
+    if (mState == State::INIT) {
+        LOG(ERROR) << __func__ << ": instance not open yet";
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE, "StateError");
+    }
+    LOG(DEBUG) << __func__ << " with: " << in_param.toString();
+    auto tag = in_param.getTag();
+    switch (tag) {
+        case Parameter::common: {
+            return setCommonParameter(in_param.get<Parameter::common>());
+        }
+        case Parameter::specific: {
+            return setSpecificParameter(in_param.get<Parameter::specific>());
+        }
+        default:
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "ParameterNotSupported");
+    }
+}
+
+ndk::ScopedAStatus EqualizerSw::getParameter(const Parameter::Id& in_paramId,
+                                             Parameter* _aidl_return) {
+    LOG(DEBUG) << __func__ << in_paramId.toString();
+    auto tag = in_paramId.getTag();
+    switch (tag) {
+        case Parameter::Id::commonTag: {
+            _aidl_return->set<Parameter::common>(mCommonParam);
+            LOG(DEBUG) << __func__ << " get: " << _aidl_return->toString();
+            return ndk::ScopedAStatus::ok();
+        }
+        case Parameter::Id::specificId: {
+            auto& id = in_paramId.get<Parameter::Id::specificId>();
+            Parameter::Specific specific;
+            ndk::ScopedAStatus status = getSpecificParameter(id, &specific);
+            if (!status.isOk()) {
+                LOG(ERROR) << __func__
+                           << " getSpecificParameter error: " << status.getDescription();
+                return status;
+            }
+            _aidl_return->set<Parameter::specific>(specific);
+            LOG(DEBUG) << __func__ << _aidl_return->toString();
+            return ndk::ScopedAStatus::ok();
+        }
+        case Parameter::Id::vendorTag: {
+            LOG(DEBUG) << __func__ << " noop for vendor tag now";
+            return ndk::ScopedAStatus::ok();
+        }
+    }
+    LOG(ERROR) << " unsupported tag: " << toString(tag);
+    return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                            "Parameter:IdNotSupported");
+}
+
+ndk::ScopedAStatus EqualizerSw::getState(State* _aidl_return) {
+    *_aidl_return = mState;
+    return ndk::ScopedAStatus::ok();
+}
+
+/// Private methods.
+ndk::ScopedAStatus EqualizerSw::setCommonParameter(const Parameter::Common& common) {
+    mCommonParam = common;
+    LOG(DEBUG) << __func__ << " set: " << mCommonParam.toString();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EqualizerSw::setSpecificParameter(const Parameter::Specific& specific) {
+    if (Parameter::Specific::equalizer != specific.getTag()) {
+        LOG(ERROR) << " unsupported effect: " << specific.toString();
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                "EffectNotSupported");
+    }
+
+    auto& eqParam = specific.get<Parameter::Specific::equalizer>();
+    auto tag = eqParam.getTag();
+    switch (tag) {
+        case Equalizer::bandLevels: {
+            auto& bandLevels = eqParam.get<Equalizer::bandLevels>();
+            const auto& [minItem, maxItem] = std::minmax_element(
+                    bandLevels.begin(), bandLevels.end(),
+                    [](const auto& a, const auto& b) { return a.index < b.index; });
+            if (bandLevels.size() >= NUM_OF_BANDS || minItem->index < 0 ||
+                maxItem->index >= NUM_OF_BANDS) {
+                LOG(ERROR) << " bandLevels " << bandLevels.size() << "minIndex " << minItem->index
+                           << "maxIndex " << maxItem->index << " illegal ";
+                return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                        "ExceedMaxBandNum");
+            }
+            mBandLevels = bandLevels;
+            return ndk::ScopedAStatus::ok();
+        }
+        case Equalizer::preset: {
+            int preset = eqParam.get<Equalizer::preset>();
+            if (preset < 0 || preset >= NUM_OF_PRESETS) {
+                LOG(ERROR) << " preset: " << preset << " invalid";
+                return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                        "ExceedMaxBandNum");
+            }
+            mPreset = preset;
+            LOG(DEBUG) << __func__ << " preset set to " << mPreset;
+            return ndk::ScopedAStatus::ok();
+        }
+        case Equalizer::vendor: {
+            LOG(DEBUG) << __func__ << " noop for vendor tag now";
+            return ndk::ScopedAStatus::ok();
+        }
+    }
+
+    LOG(ERROR) << __func__ << " unsupported eq param tag: " << toString(tag);
+    return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                            "ParamNotSupported");
+}
+
+ndk::ScopedAStatus EqualizerSw::getSpecificParameter(Parameter::Specific::Id id,
+                                                     Parameter::Specific* specific) {
+    Equalizer eqParam;
+    auto tag = id.getTag();
+    if (tag != Parameter::Specific::Id::equalizerTag) {
+        LOG(ERROR) << " invalid tag: " << toString(tag);
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                "UnsupportedTag");
+    }
+    auto eqTag = id.get<Parameter::Specific::Id::equalizerTag>();
+    switch (eqTag) {
+        case Equalizer::bandLevels: {
+            eqParam.set<Equalizer::bandLevels>(mBandLevels);
+            specific->set<Parameter::Specific::equalizer>(eqParam);
+            return ndk::ScopedAStatus::ok();
+        }
+        case Equalizer::preset: {
+            eqParam.set<Equalizer::preset>(mPreset);
+            LOG(DEBUG) << __func__ << " preset " << mPreset;
+            specific->set<Parameter::Specific::equalizer>(eqParam);
+            return ndk::ScopedAStatus::ok();
+        }
+        case Equalizer::vendor: {
+            LOG(DEBUG) << __func__ << " noop for vendor tag now";
+            return ndk::ScopedAStatus::ok();
+        }
+    }
+    LOG(ERROR) << __func__ << " unsupported eq param: " << toString(eqTag);
+    return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                            "ParamNotSupported");
+}
+
+void EqualizerSw::cleanUp() {
+    if (State::PROCESSING == mState) {
+        command(CommandId::STOP);
+    }
+    if (State::INIT != mState) {
+        close();
+    }
+}
+
+IEffect::Status EqualizerSw::status(binder_status_t status, size_t consumed, size_t produced) {
+    IEffect::Status ret;
+    ret.status = status;
+    ret.fmqByteConsumed = consumed;
+    ret.fmqByteProduced = produced;
+    return ret;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status EqualizerSw::effectProcessImpl() {
+    // TODO: get data buffer and process.
+    return status(STATUS_OK, mContext->availableToRead(), mContext->availableToWrite());
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/core-impl/Config.h b/audio/aidl/default/include/core-impl/Config.h
new file mode 100644
index 0000000..4555efd
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/Config.h
@@ -0,0 +1,27 @@
+/*
+ * 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 <aidl/android/hardware/audio/core/BnConfig.h>
+
+namespace aidl::android::hardware::audio::core {
+
+class Config : public BnConfig {
+    ndk::ScopedAStatus getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) override;
+};
+
+}  // 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
new file mode 100644
index 0000000..d5cd30b
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/Configuration.h
@@ -0,0 +1,44 @@
+/*
+ * 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 <map>
+#include <vector>
+
+#include <aidl/android/hardware/audio/core/AudioPatch.h>
+#include <aidl/android/hardware/audio/core/AudioRoute.h>
+#include <aidl/android/media/audio/common/AudioPort.h>
+#include <aidl/android/media/audio/common/AudioPortConfig.h>
+
+namespace aidl::android::hardware::audio::core::internal {
+
+struct Configuration {
+    std::vector<::aidl::android::media::audio::common::AudioPort> ports;
+    std::vector<::aidl::android::media::audio::common::AudioPortConfig> portConfigs;
+    std::vector<::aidl::android::media::audio::common::AudioPortConfig> initialConfigs;
+    // Port id -> List of profiles to use when the device port state is set to 'connected'.
+    std::map<int32_t, std::vector<::aidl::android::media::audio::common::AudioProfile>>
+            connectedProfiles;
+    std::vector<AudioRoute> routes;
+    std::vector<AudioPatch> patches;
+    int32_t nextPortId = 1;
+    int32_t nextPatchId = 1;
+};
+
+Configuration& getNullPrimaryConfiguration();
+
+}  // 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
new file mode 100644
index 0000000..61516b2
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -0,0 +1,99 @@
+/*
+ * 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 <map>
+#include <memory>
+#include <set>
+
+#include <aidl/android/hardware/audio/core/BnModule.h>
+
+#include "core-impl/Configuration.h"
+#include "core-impl/Stream.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class Module : public BnModule {
+  public:
+    // This value is used for all AudioPatches and reported by all streams.
+    static constexpr int32_t kLatencyMs = 10;
+
+  private:
+    ndk::ScopedAStatus setModuleDebug(
+            const ::aidl::android::hardware::audio::core::ModuleDebug& in_debug) override;
+    ndk::ScopedAStatus connectExternalDevice(
+            const ::aidl::android::media::audio::common::AudioPort& in_templateIdAndAdditionalData,
+            ::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
+    ndk::ScopedAStatus disconnectExternalDevice(int32_t in_portId) override;
+    ndk::ScopedAStatus getAudioPatches(std::vector<AudioPatch>* _aidl_return) override;
+    ndk::ScopedAStatus getAudioPort(
+            int32_t in_portId,
+            ::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
+    ndk::ScopedAStatus getAudioPortConfigs(
+            std::vector<::aidl::android::media::audio::common::AudioPortConfig>* _aidl_return)
+            override;
+    ndk::ScopedAStatus getAudioPorts(
+            std::vector<::aidl::android::media::audio::common::AudioPort>* _aidl_return) override;
+    ndk::ScopedAStatus getAudioRoutes(std::vector<AudioRoute>* _aidl_return) override;
+    ndk::ScopedAStatus getAudioRoutesForAudioPort(
+            int32_t in_portId,
+            std::vector<::aidl::android::hardware::audio::core::AudioRoute>* _aidl_return) override;
+    ndk::ScopedAStatus openInputStream(
+            const ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments&
+                    in_args,
+            ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn* _aidl_return)
+            override;
+    ndk::ScopedAStatus openOutputStream(
+            const ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments&
+                    in_args,
+            ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn* _aidl_return)
+            override;
+    ndk::ScopedAStatus setAudioPatch(const AudioPatch& in_requested,
+                                     AudioPatch* _aidl_return) override;
+    ndk::ScopedAStatus setAudioPortConfig(
+            const ::aidl::android::media::audio::common::AudioPortConfig& in_requested,
+            ::aidl::android::media::audio::common::AudioPortConfig* out_suggested,
+            bool* _aidl_return) override;
+    ndk::ScopedAStatus resetAudioPatch(int32_t in_patchId) override;
+    ndk::ScopedAStatus resetAudioPortConfig(int32_t in_portConfigId) override;
+
+    void cleanUpPatch(int32_t patchId);
+    ndk::ScopedAStatus createStreamContext(
+            int32_t in_portConfigId, int64_t in_bufferSizeFrames,
+            ::aidl::android::hardware::audio::core::StreamContext* out_context);
+    ndk::ScopedAStatus findPortIdForNewStream(
+            int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
+    internal::Configuration& getConfig();
+    void registerPatch(const AudioPatch& patch);
+    void updateStreamsConnectedState(const AudioPatch& oldPatch, const AudioPatch& newPatch);
+
+    // This value is used for all AudioPatches.
+    static constexpr int32_t kMinimumStreamBufferSizeFrames = 16;
+    // The maximum stream buffer size is 1 GiB = 2 ** 30 bytes;
+    static constexpr int32_t kMaximumStreamBufferSizeBytes = 1 << 30;
+
+    std::unique_ptr<internal::Configuration> mConfig;
+    ModuleDebug mDebug;
+    // ids of ports created at runtime via 'connectExternalDevice'.
+    std::set<int32_t> mConnectedDevicePorts;
+    Streams mStreams;
+    // Maps port ids and port config ids to patch ids.
+    // Multimap because both ports and configs can be used by multiple patches.
+    std::multimap<int32_t, int32_t> mPatches;
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
new file mode 100644
index 0000000..488edf1
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -0,0 +1,269 @@
+/*
+ * 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 <atomic>
+#include <cstdlib>
+#include <map>
+#include <memory>
+#include <optional>
+#include <variant>
+
+#include <StreamWorker.h>
+#include <aidl/android/hardware/audio/common/SinkMetadata.h>
+#include <aidl/android/hardware/audio/common/SourceMetadata.h>
+#include <aidl/android/hardware/audio/core/BnStreamIn.h>
+#include <aidl/android/hardware/audio/core/BnStreamOut.h>
+#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
+#include <aidl/android/media/audio/common/AudioOffloadInfo.h>
+#include <fmq/AidlMessageQueue.h>
+#include <system/thread_defs.h>
+
+#include "core-impl/utils.h"
+
+namespace aidl::android::hardware::audio::core {
+
+// This class is similar to StreamDescriptor, but unlike
+// the descriptor, it actually owns the objects implementing
+// data exchange: FMQs etc, whereas StreamDescriptor only
+// contains their descriptors.
+class StreamContext {
+  public:
+    typedef ::android::AidlMessageQueue<
+            StreamDescriptor::Command,
+            ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+            CommandMQ;
+    typedef ::android::AidlMessageQueue<
+            StreamDescriptor::Reply, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+            ReplyMQ;
+    typedef ::android::AidlMessageQueue<
+            int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+            DataMQ;
+
+    // Ensure that this value is not used by any of StreamDescriptor.COMMAND_*
+    static constexpr int COMMAND_EXIT = -1;
+
+    StreamContext() = default;
+    StreamContext(std::unique_ptr<CommandMQ> commandMQ, std::unique_ptr<ReplyMQ> replyMQ,
+                  size_t frameSize, std::unique_ptr<DataMQ> dataMQ)
+        : mCommandMQ(std::move(commandMQ)),
+          mInternalCommandCookie(std::rand()),
+          mReplyMQ(std::move(replyMQ)),
+          mFrameSize(frameSize),
+          mDataMQ(std::move(dataMQ)) {}
+    StreamContext(StreamContext&& other)
+        : mCommandMQ(std::move(other.mCommandMQ)),
+          mInternalCommandCookie(other.mInternalCommandCookie),
+          mReplyMQ(std::move(other.mReplyMQ)),
+          mFrameSize(other.mFrameSize),
+          mDataMQ(std::move(other.mDataMQ)) {}
+    StreamContext& operator=(StreamContext&& other) {
+        mCommandMQ = std::move(other.mCommandMQ);
+        mInternalCommandCookie = other.mInternalCommandCookie;
+        mReplyMQ = std::move(other.mReplyMQ);
+        mFrameSize = other.mFrameSize;
+        mDataMQ = std::move(other.mDataMQ);
+        return *this;
+    }
+
+    void fillDescriptor(StreamDescriptor* desc);
+    CommandMQ* getCommandMQ() const { return mCommandMQ.get(); }
+    DataMQ* getDataMQ() const { return mDataMQ.get(); }
+    size_t getFrameSize() const { return mFrameSize; }
+    int getInternalCommandCookie() const { return mInternalCommandCookie; }
+    ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
+    bool isValid() const;
+    void reset();
+
+  private:
+    std::unique_ptr<CommandMQ> mCommandMQ;
+    int mInternalCommandCookie;  // The value used to confirm that the command was posted internally
+    std::unique_ptr<ReplyMQ> mReplyMQ;
+    size_t mFrameSize;
+    std::unique_ptr<DataMQ> mDataMQ;
+};
+
+class StreamWorkerCommonLogic : public ::android::hardware::audio::common::StreamLogic {
+  public:
+    void setIsConnected(bool connected) { mIsConnected = connected; }
+
+  protected:
+    explicit StreamWorkerCommonLogic(const StreamContext& context)
+        : mInternalCommandCookie(context.getInternalCommandCookie()),
+          mFrameSize(context.getFrameSize()),
+          mCommandMQ(context.getCommandMQ()),
+          mReplyMQ(context.getReplyMQ()),
+          mDataMQ(context.getDataMQ()) {}
+    std::string init() override;
+
+    // Used both by the main and worker threads.
+    std::atomic<bool> mIsConnected = false;
+    // All fields are used on the worker thread only.
+    const int mInternalCommandCookie;
+    const size_t mFrameSize;
+    StreamContext::CommandMQ* mCommandMQ;
+    StreamContext::ReplyMQ* mReplyMQ;
+    StreamContext::DataMQ* mDataMQ;
+    // We use an array and the "size" field instead of a vector to be able to detect
+    // memory allocation issues.
+    std::unique_ptr<int8_t[]> mDataBuffer;
+    size_t mDataBufferSize;
+    long mFrameCount = 0;
+};
+
+class StreamInWorkerLogic : public StreamWorkerCommonLogic {
+  public:
+    static const std::string kThreadName;
+    explicit StreamInWorkerLogic(const StreamContext& context) : StreamWorkerCommonLogic(context) {}
+
+  protected:
+    Status cycle() override;
+};
+using StreamInWorker = ::android::hardware::audio::common::StreamWorker<StreamInWorkerLogic>;
+
+class StreamOutWorkerLogic : public StreamWorkerCommonLogic {
+  public:
+    static const std::string kThreadName;
+    explicit StreamOutWorkerLogic(const StreamContext& context)
+        : StreamWorkerCommonLogic(context) {}
+
+  protected:
+    Status cycle() override;
+};
+using StreamOutWorker = ::android::hardware::audio::common::StreamWorker<StreamOutWorkerLogic>;
+
+template <class Metadata, class StreamWorker>
+class StreamCommon {
+  public:
+    ndk::ScopedAStatus close();
+    ndk::ScopedAStatus init() {
+        return mWorker.start(StreamWorker::kThreadName, ANDROID_PRIORITY_AUDIO)
+                       ? ndk::ScopedAStatus::ok()
+                       : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    bool isClosed() const { return mIsClosed; }
+    void setIsConnected(bool connected) { mWorker.setIsConnected(connected); }
+    ndk::ScopedAStatus updateMetadata(const Metadata& metadata);
+
+  protected:
+    StreamCommon(const Metadata& metadata, StreamContext context)
+        : mMetadata(metadata), mContext(std::move(context)), mWorker(mContext) {}
+    ~StreamCommon();
+    void stopWorker();
+
+    Metadata mMetadata;
+    StreamContext mContext;
+    StreamWorker mWorker;
+    // This variable is checked in the destructor which can be called on an arbitrary Binder thread,
+    // thus we need to ensure that any changes made by other threads are sequentially consistent.
+    std::atomic<bool> mIsClosed = false;
+};
+
+class StreamIn
+    : public StreamCommon<::aidl::android::hardware::audio::common::SinkMetadata, StreamInWorker>,
+      public BnStreamIn {
+    ndk::ScopedAStatus close() override {
+        return StreamCommon<::aidl::android::hardware::audio::common::SinkMetadata,
+                            StreamInWorker>::close();
+    }
+    ndk::ScopedAStatus updateMetadata(const ::aidl::android::hardware::audio::common::SinkMetadata&
+                                              in_sinkMetadata) override {
+        return StreamCommon<::aidl::android::hardware::audio::common::SinkMetadata,
+                            StreamInWorker>::updateMetadata(in_sinkMetadata);
+    }
+
+  public:
+    StreamIn(const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+             StreamContext context);
+};
+
+class StreamOut : public StreamCommon<::aidl::android::hardware::audio::common::SourceMetadata,
+                                      StreamOutWorker>,
+                  public BnStreamOut {
+    ndk::ScopedAStatus close() override {
+        return StreamCommon<::aidl::android::hardware::audio::common::SourceMetadata,
+                            StreamOutWorker>::close();
+    }
+    ndk::ScopedAStatus updateMetadata(
+            const ::aidl::android::hardware::audio::common::SourceMetadata& in_sourceMetadata)
+            override {
+        return StreamCommon<::aidl::android::hardware::audio::common::SourceMetadata,
+                            StreamOutWorker>::updateMetadata(in_sourceMetadata);
+    }
+
+  public:
+    StreamOut(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+              StreamContext context,
+              const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                      offloadInfo);
+
+  private:
+    std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
+};
+
+class StreamWrapper {
+  public:
+    explicit StreamWrapper(std::shared_ptr<StreamIn> streamIn) : mStream(streamIn) {}
+    explicit StreamWrapper(std::shared_ptr<StreamOut> streamOut) : mStream(streamOut) {}
+    bool isStreamOpen() const {
+        return std::visit(
+                [](auto&& ws) -> bool {
+                    auto s = ws.lock();
+                    return s && !s->isClosed();
+                },
+                mStream);
+    }
+    void setStreamIsConnected(bool connected) {
+        std::visit(
+                [&](auto&& ws) {
+                    auto s = ws.lock();
+                    if (s) s->setIsConnected(connected);
+                },
+                mStream);
+    }
+
+  private:
+    std::variant<std::weak_ptr<StreamIn>, std::weak_ptr<StreamOut>> mStream;
+};
+
+class Streams {
+  public:
+    Streams() = default;
+    Streams(const Streams&) = delete;
+    Streams& operator=(const Streams&) = delete;
+    size_t count(int32_t id) {
+        // Streams do not remove themselves from the collection on close.
+        erase_if(mStreams, [](const auto& pair) { return !pair.second.isStreamOpen(); });
+        return mStreams.count(id);
+    }
+    void insert(int32_t portId, int32_t portConfigId, StreamWrapper sw) {
+        mStreams.insert(std::pair{portConfigId, sw});
+        mStreams.insert(std::pair{portId, std::move(sw)});
+    }
+    void setStreamIsConnected(int32_t portConfigId, bool connected) {
+        if (auto it = mStreams.find(portConfigId); it != mStreams.end()) {
+            it->second.setStreamIsConnected(connected);
+        }
+    }
+
+  private:
+    // Maps port ids and port config ids to streams. Multimap because a port
+    // (not port config) can have multiple streams opened on it.
+    std::multimap<int32_t, StreamWrapper> mStreams;
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/utils.h b/audio/aidl/default/include/core-impl/utils.h
new file mode 100644
index 0000000..9d06f08
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/utils.h
@@ -0,0 +1,104 @@
+/*
+ * 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 <algorithm>
+#include <set>
+#include <vector>
+
+namespace aidl::android::hardware::audio::core {
+
+// Return whether all the elements in the vector are unique.
+template <typename T>
+bool all_unique(const std::vector<T>& v) {
+    return std::set<T>(v.begin(), v.end()).size() == v.size();
+}
+
+// Erase all the specified elements from a map.
+template <typename C, typename V>
+auto erase_all(C& c, const V& keys) {
+    auto oldSize = c.size();
+    for (auto& k : keys) {
+        c.erase(k);
+    }
+    return oldSize - c.size();
+}
+
+// Erase all the elements in the container that satisfy the provided predicate.
+template <typename C, typename P>
+auto erase_if(C& c, P pred) {
+    auto oldSize = c.size();
+    for (auto it = c.begin(); it != c.end();) {
+        if (pred(*it)) {
+            it = c.erase(it);
+        } else {
+            ++it;
+        }
+    }
+    return oldSize - c.size();
+}
+
+// Erase all the elements in the map that have specified values.
+template <typename C, typename V>
+auto erase_all_values(C& c, const V& values) {
+    return erase_if(c, [values](const auto& pair) { return values.count(pair.second) != 0; });
+}
+
+// Return non-zero count of elements for any of the provided keys.
+template <typename M, typename V>
+size_t count_any(const M& m, const V& keys) {
+    for (auto& k : keys) {
+        if (size_t c = m.count(k); c != 0) return c;
+    }
+    return 0;
+}
+
+// Assuming that M is a map whose values have an 'id' field,
+// find an element with the specified id.
+template <typename M>
+auto findById(M& m, int32_t id) {
+    return std::find_if(m.begin(), m.end(), [&](const auto& p) { return p.second.id == id; });
+}
+
+// Assuming that the vector contains elements with an 'id' field,
+// find an element with the specified id.
+template <typename T>
+auto findById(std::vector<T>& v, int32_t id) {
+    return std::find_if(v.begin(), v.end(), [&](const auto& e) { return e.id == id; });
+}
+
+// Return elements from the vector that have specified ids, also
+// optionally return which ids were not found.
+template <typename T>
+std::vector<T*> selectByIds(std::vector<T>& v, const std::vector<int32_t>& ids,
+                            std::vector<int32_t>* missingIds = nullptr) {
+    std::vector<T*> result;
+    std::set<int32_t> idsSet(ids.begin(), ids.end());
+    for (size_t i = 0; i < v.size(); ++i) {
+        T& e = v[i];
+        if (idsSet.count(e.id) != 0) {
+            result.push_back(&v[i]);
+            idsSet.erase(e.id);
+        }
+    }
+    if (missingIds) {
+        *missingIds = std::vector(idsSet.begin(), idsSet.end());
+    }
+    return result;
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/effect-impl/EffectContext.h b/audio/aidl/default/include/effect-impl/EffectContext.h
new file mode 100644
index 0000000..36492ec
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectContext.h
@@ -0,0 +1,65 @@
+/*
+ * 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 <cstdint>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectContext {
+  public:
+    typedef ::android::AidlMessageQueue<
+            IEffect::Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+            StatusMQ;
+    typedef ::android::AidlMessageQueue<
+            int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+            DataMQ;
+
+    EffectContext(size_t statusDepth, size_t inBufferSize, size_t outBufferSize) {
+        mStatusMQ = std::make_shared<StatusMQ>(statusDepth, true /*configureEventFlagWord*/);
+        mInputMQ = std::make_shared<DataMQ>(inBufferSize);
+        mOutputMQ = std::make_shared<DataMQ>(outBufferSize);
+
+        if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) {
+            LOG(ERROR) << __func__ << " created invalid FMQ";
+        }
+        mWorkBuffer.reserve(std::max(inBufferSize, outBufferSize));
+    };
+
+    std::shared_ptr<StatusMQ> getStatusFmq() { return mStatusMQ; };
+    std::shared_ptr<DataMQ> getInputDataFmq() { return mInputMQ; };
+    std::shared_ptr<DataMQ> getOutputDataFmq() { return mOutputMQ; };
+
+    int8_t* getWorkBuffer() { return static_cast<int8_t*>(mWorkBuffer.data()); };
+    // TODO: update with actual available size
+    size_t availableToRead() { return mWorkBuffer.capacity(); };
+    size_t availableToWrite() { return mWorkBuffer.capacity(); };
+
+  private:
+    std::shared_ptr<StatusMQ> mStatusMQ;
+    std::shared_ptr<DataMQ> mInputMQ;
+    std::shared_ptr<DataMQ> mOutputMQ;
+    // TODO handle effect process input and output
+    // work buffer set by effect instances, the access and update are in same thread
+    std::vector<int8_t> mWorkBuffer;
+};
+}  // 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
new file mode 100644
index 0000000..09a0000
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectThread.h
@@ -0,0 +1,58 @@
+/*
+ * 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 <atomic>
+#include <string>
+#include <thread>
+
+#include <android-base/thread_annotations.h>
+#include <system/thread_defs.h>
+
+#include "effect-impl/EffectTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectThread {
+  public:
+    // default priority is same as HIDL: ANDROID_PRIORITY_URGENT_AUDIO
+    EffectThread();
+    virtual ~EffectThread();
+
+    // called by effect implementation.
+    RetCode createThread(const std::string& name,
+                         const int priority = ANDROID_PRIORITY_URGENT_AUDIO);
+    RetCode destroyThread();
+    RetCode startThread();
+    RetCode stopThread();
+
+    // 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;
+
+  private:
+    std::mutex mMutex;
+    std::condition_variable mCv;
+    bool mExit GUARDED_BY(mMutex) = false;
+    bool mStop GUARDED_BY(mMutex) = true;
+    std::thread mThread;
+    int mPriority;
+    std::string mName;
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectTypes.h b/audio/aidl/default/include/effect-impl/EffectTypes.h
new file mode 100644
index 0000000..46cfc0c
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectTypes.h
@@ -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.
+ */
+
+#pragma once
+#include <ostream>
+#include <string>
+
+namespace aidl::android::hardware::audio::effect {
+
+enum class RetCode {
+    SUCCESS,
+    ERROR_ILLEGAL_PARAMETER, /* Illegal parameter */
+    ERROR_THREAD,            /* Effect thread error */
+    ERROR_NULL_POINTER,      /* NULL pointer */
+    ERROR_ALIGNMENT_ERROR,   /* Memory alignment error */
+    ERROR_BLOCK_SIZE_EXCEED  /* Maximum block size exceeded */
+};
+
+inline std::ostream& operator<<(std::ostream& out, const RetCode& code) {
+    switch (code) {
+        case RetCode::SUCCESS:
+            return out << "SUCCESS";
+        case RetCode::ERROR_ILLEGAL_PARAMETER:
+            return out << "ERROR_ILLEGAL_PARAMETER";
+        case RetCode::ERROR_THREAD:
+            return out << "ERROR_THREAD";
+        case RetCode::ERROR_NULL_POINTER:
+            return out << "ERROR_NULL_POINTER";
+        case RetCode::ERROR_ALIGNMENT_ERROR:
+            return out << "ERROR_ALIGNMENT_ERROR";
+        case RetCode::ERROR_BLOCK_SIZE_EXCEED:
+            return out << "ERROR_BLOCK_SIZE_EXCEED";
+    }
+
+    return out << "EnumError: " << code;
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h
new file mode 100644
index 0000000..48b7137
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectUUID.h
@@ -0,0 +1,56 @@
+/*
+ * 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 <aidl/android/media/audio/common/AudioUuid.h>
+
+namespace aidl::android::hardware::audio::effect {
+
+using ::aidl::android::media::audio::common::AudioUuid;
+
+// Null UUID
+static const AudioUuid EffectNullUuid = {static_cast<int32_t>(0xec7178ec),
+                                         0xe5e1,
+                                         0x4432,
+                                         0xa3f4,
+                                         {0x46, 0x57, 0xe6, 0x79, 0x52, 0x10}};
+
+// Zero UUID
+static const AudioUuid EffectZeroUuid = {
+        static_cast<int32_t>(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
+
+// Equalizer type UUID.
+static const AudioUuid EqualizerTypeUUID = {static_cast<int32_t>(0x0bed4300),
+                                            0xddd6,
+                                            0x11db,
+                                            0x8f34,
+                                            {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+
+// Equalizer implementation UUID.
+static const AudioUuid EqualizerSwImplUUID = {static_cast<int32_t>(0x0bed4300),
+                                              0x847d,
+                                              0x11df,
+                                              0xbb17,
+                                              {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+
+// Visualizer type UUID.
+static const AudioUuid VisualizerTypeUUID = {static_cast<int32_t>(0x1d4033c0),
+                                             0x8557,
+                                             0x11df,
+                                             0x9f2d,
+                                             {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectWorker.h b/audio/aidl/default/include/effect-impl/EffectWorker.h
new file mode 100644
index 0000000..0fe69ff
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectWorker.h
@@ -0,0 +1,74 @@
+/*
+ * 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 <algorithm>
+#include <memory>
+#include <mutex>
+#include <string>
+
+#include "EffectContext.h"
+#include "EffectThread.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+std::string toString(RetCode& code);
+
+class EffectWorker : public EffectThread {
+  public:
+    // set effect context for worker, suppose to only happen once here
+    void setContext(std::shared_ptr<EffectContext> context) {
+        std::call_once(mOnceFlag, [&]() { mContext = context; });
+    };
+
+    // handle FMQ and call effect implemented virtual function
+    void process() override {
+        if (!mContext) {
+            LOG(ERROR) << __func__ << " invalid context!";
+            return;
+        }
+        std::shared_ptr<EffectContext::StatusMQ> statusMQ = mContext->getStatusFmq();
+        std::shared_ptr<EffectContext::DataMQ> inputMQ = mContext->getInputDataFmq();
+        std::shared_ptr<EffectContext::DataMQ> outputMQ = mContext->getOutputDataFmq();
+
+        // Only this worker will read from input data MQ and write to output data MQ.
+        auto readSize = inputMQ->availableToRead(), writeSize = outputMQ->availableToWrite();
+        if (readSize && writeSize) {
+            LOG(DEBUG) << __func__ << " available to read " << readSize << " available to write "
+                       << writeSize;
+            auto buffer = mContext->getWorkBuffer();
+            inputMQ->read(buffer, readSize);
+            IEffect::Status status = effectProcessImpl();
+            writeSize = std::min((int32_t)writeSize, status.fmqByteProduced);
+            outputMQ->write(buffer, writeSize);
+            statusMQ->writeBlocking(&status, 1);
+            LOG(DEBUG) << __func__ << " done processing, effect consumed " << status.fmqByteConsumed
+                       << " produced " << status.fmqByteProduced;
+        } else {
+            // TODO: maybe add some sleep here to avoid busy waiting
+        }
+    }
+
+    // must implement by each effect implementation
+    virtual IEffect::Status effectProcessImpl() = 0;
+
+  private:
+    // make sure the context only set once.
+    std::once_flag mOnceFlag;
+    std::shared_ptr<EffectContext> mContext;
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
new file mode 100644
index 0000000..6195d8a
--- /dev/null
+++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
@@ -0,0 +1,100 @@
+/*
+ * 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 <any>
+#include <map>
+#include <optional>
+#include <vector>
+
+#include <aidl/android/hardware/audio/effect/BnFactory.h>
+
+namespace aidl::android::hardware::audio::effect {
+
+class Factory : public BnFactory {
+  public:
+    Factory();
+    /**
+     * @brief Get identity of all effects supported by the device, with the optional filter by type
+     * and/or by instance UUID.
+     *
+     * @param in_type Type UUID.
+     * @param in_instance Instance UUID.
+     * @param out_descriptor List of identities .
+     * @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,
+            std::vector<Descriptor::Identity>* out_descriptor) override;
+
+    /**
+     * @brief Query list of defined processing, with the optional filter by AudioStreamType
+     *
+     * @param in_type Type of processing, could be AudioStreamType or AudioSource. Optional.
+     * @param _aidl_return List of processing filtered by in_type.
+     * @return ndk::ScopedAStatus
+     */
+    ndk::ScopedAStatus queryProcessing(const std::optional<Processing::Type>& in_type,
+                                       std::vector<Processing>* _aidl_return) override;
+
+    /**
+     * @brief Create an effect instance for a certain implementation (identified by UUID).
+     *
+     * @param in_impl_uuid Effect implementation UUID.
+     * @param _aidl_return A pointer to created effect instance.
+     * @return ndk::ScopedAStatus
+     */
+    ndk::ScopedAStatus createEffect(
+            const ::aidl::android::media::audio::common::AudioUuid& in_impl_uuid,
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>* _aidl_return)
+            override;
+
+    /**
+     * @brief Destroy an effect instance.
+     *
+     * @param in_handle Effect instance handle.
+     * @return ndk::ScopedAStatus
+     */
+    ndk::ScopedAStatus destroyEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_handle)
+            override;
+
+  private:
+    ~Factory();
+    // List of effect descriptors supported by the devices.
+    std::vector<Descriptor::Identity> mIdentityList;
+
+    typedef binder_exception_t (*EffectCreateFunctor)(std::shared_ptr<IEffect>*);
+    typedef binder_exception_t (*EffectDestroyFunctor)(const std::shared_ptr<IEffect>&);
+    struct effect_interface_s {
+        EffectCreateFunctor createEffectFunc;
+        EffectDestroyFunctor destroyEffectFunc;
+    };
+
+    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_interface_s>>>
+            mEffectLibMap;
+    std::map<std::weak_ptr<IEffect>, aidl::android::media::audio::common::AudioUuid,
+             std::owner_less<>>
+            mEffectUuidMap;
+
+    ndk::ScopedAStatus destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle);
+    void cleanupEffectMap();
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/equalizer-impl/EqualizerSw.h b/audio/aidl/default/include/equalizer-impl/EqualizerSw.h
new file mode 100644
index 0000000..aa3a727
--- /dev/null
+++ b/audio/aidl/default/include/equalizer-impl/EqualizerSw.h
@@ -0,0 +1,105 @@
+/*
+ * 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 <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectContext.h"
+#include "effect-impl/EffectTypes.h"
+#include "effect-impl/EffectUUID.h"
+#include "effect-impl/EffectWorker.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EqualizerSwContext : public EffectContext {
+  public:
+    EqualizerSwContext(int statusDepth, int inBufferSize, int outBufferSize)
+        : EffectContext(statusDepth, inBufferSize, outBufferSize) {
+        LOG(DEBUG) << __func__;
+    }
+
+  private:
+    // Add equalizer specific context for processing here
+};
+
+class EqualizerSw : public BnEffect, EffectWorker {
+  public:
+    EqualizerSw() {
+        Equalizer::Capability eqCap = {.bandFrequencies = mBandFrequency, .presets = mPresets};
+        mDesc.capability.set<Capability::equalizer>(eqCap);
+        LOG(DEBUG) << __func__;
+    };
+    ~EqualizerSw() {
+        cleanUp();
+        LOG(DEBUG) << __func__;
+    };
+    ndk::ScopedAStatus open(const Parameter::Common& common, const Parameter::Specific& specific,
+                            OpenEffectReturn* _aidl_return) override;
+    ndk::ScopedAStatus close() override;
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+
+    ndk::ScopedAStatus getState(State* _aidl_return) override;
+    ndk::ScopedAStatus command(CommandId in_commandId) override;
+    ndk::ScopedAStatus setParameter(const Parameter& in_param) override;
+    ndk::ScopedAStatus getParameter(const Parameter::Id& in_paramId,
+                                    Parameter* _aidl_return) override;
+
+    IEffect::Status effectProcessImpl() override;
+
+  private:
+    // Effect descriptor.
+    Descriptor mDesc = {.common = {.id = {.type = EqualizerTypeUUID, .uuid = EqualizerSwImplUUID}}};
+
+    // Parameters.
+    Parameter::Common mCommonParam;
+    Equalizer mEqualizerParam;  // TODO: the equalizer parameter needs to update
+
+    // Instance state INIT by default.
+    State mState = State::INIT;
+
+    int mPreset = PRESET_CUSTOM;  // the current preset
+    const std::vector<Equalizer::BandFrequency> mBandFrequency = {{0, 30000, 120000},
+                                                                  {1, 120001, 460000},
+                                                                  {2, 460001, 1800000},
+                                                                  {3, 1800001, 7000000},
+                                                                  {4, 7000001, 20000000}};
+    // preset band level
+    std::vector<Equalizer::BandLevel> mBandLevels = {{0, 3}, {1, 0}, {2, 0}, {3, 0}, {4, 3}};
+    // 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"}};
+    static const int NUM_OF_BANDS = 5;
+    static const int NUM_OF_PRESETS = 10;
+    static const int PRESET_CUSTOM = -1;
+
+    // Equalizer worker context
+    std::shared_ptr<EqualizerSwContext> mContext;
+
+    ndk::ScopedAStatus setCommonParameter(const Parameter::Common& common_param);
+    ndk::ScopedAStatus setSpecificParameter(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getSpecificParameter(Parameter::Specific::Id id,
+                                            Parameter::Specific* specific);
+
+    void cleanUp();
+
+    IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/main.cpp b/audio/aidl/default/main.cpp
new file mode 100644
index 0000000..15874a0
--- /dev/null
+++ b/audio/aidl/default/main.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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 <cstdlib>
+#include <ctime>
+
+#include "core-impl/Config.h"
+#include "core-impl/Module.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::audio::core::Config;
+using aidl::android::hardware::audio::core::Module;
+
+int main() {
+    // Random values are used in the implementation.
+    std::srand(std::time(nullptr));
+
+    // This is a debug implementation, always enable debug logging.
+    android::base::SetMinimumLogSeverity(::android::base::DEBUG);
+    ABinderProcess_setThreadPoolMaxThreadCount(16);
+
+    // Make the default config service
+    auto config = ndk::SharedRefBase::make<Config>();
+    const std::string configName = std::string() + Config::descriptor + "/default";
+    binder_status_t status =
+            AServiceManager_addService(config->asBinder().get(), configName.c_str());
+    CHECK_EQ(STATUS_OK, status);
+
+    // Make the default module
+    auto moduleDefault = ndk::SharedRefBase::make<Module>();
+    const std::string moduleDefaultName = std::string() + Module::descriptor + "/default";
+    status = AServiceManager_addService(moduleDefault->asBinder().get(), moduleDefaultName.c_str());
+    CHECK_EQ(STATUS_OK, status);
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reach
+}
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
new file mode 100644
index 0000000..8de1d79
--- /dev/null
+++ b/audio/aidl/vts/Android.bp
@@ -0,0 +1,142 @@
+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: "VtsHalAudioCoreTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+        "latest_android_hardware_audio_common_ndk_static",
+        "latest_android_hardware_audio_core_ndk_static",
+        "latest_android_media_audio_common_types_ndk_static",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libcutils",
+        "libfmq",
+    ],
+    static_libs: [
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+        "libaudioaidlcommon",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+    ],
+    srcs: [
+        "ModuleConfig.cpp",
+        "VtsHalAudioCoreTargetTest.cpp",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
+
+cc_test {
+    name: "VtsHalAudioEffectFactoryTargetTest",
+    defaults: [
+        "latest_android_media_audio_common_types_ndk_static",
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsHalAudioEffectFactoryTargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.audio.effect-V1-ndk",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+    ],
+    header_libs: ["libaudioaidl_headers"],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
+
+cc_test {
+    name: "VtsHalAudioEffectTargetTest",
+    defaults: [
+        "latest_android_hardware_audio_common_ndk_static",
+        "latest_android_media_audio_common_types_ndk_static",
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsHalAudioEffectTargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libfmq",
+    ],
+    static_libs: [
+        "android.hardware.audio.effect-V1-ndk",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+        "libaudioaidlcommon",
+    ],
+    header_libs: ["libaudioaidl_headers"],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
+
+cc_test {
+    name: "VtsHalEqualizerTargetTest",
+    defaults: [
+        "latest_android_hardware_audio_common_ndk_static",
+        "latest_android_media_audio_common_types_ndk_static",
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsHalEqualizerTargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libfmq",
+    ],
+    static_libs: [
+        "android.hardware.audio.effect-V1-ndk",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+        "libaudioaidlcommon",
+    ],
+    header_libs: ["libaudioaidl_headers"],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/audio/aidl/vts/AudioHalBinderServiceUtil.h b/audio/aidl/vts/AudioHalBinderServiceUtil.h
new file mode 100644
index 0000000..e928286
--- /dev/null
+++ b/audio/aidl/vts/AudioHalBinderServiceUtil.h
@@ -0,0 +1,99 @@
+/*
+ * 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 <condition_variable>
+#include <memory>
+#include <mutex>
+
+#include <android-base/properties.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include <android-base/logging.h>
+
+class AudioHalBinderServiceUtil {
+  public:
+    ndk::SpAIBinder connectToService(const std::string& serviceName) {
+        mServiceName = serviceName;
+        mBinder = ndk::SpAIBinder(AServiceManager_getService(serviceName.c_str()));
+        if (mBinder == nullptr) {
+            LOG(ERROR) << "Failed to get service " << serviceName;
+        } else {
+            LOG(DEBUG) << "succeed to get service " << serviceName;
+        }
+        return mBinder;
+    }
+
+    ndk::SpAIBinder restartService(
+            std::chrono::milliseconds timeoutMs = std::chrono::milliseconds(3000)) {
+        mDeathHandler.reset(new AidlDeathRecipient(mBinder));
+        if (STATUS_OK != mDeathHandler->linkToDeath()) {
+            LOG(ERROR) << "linkToDeath failed";
+            return nullptr;
+        }
+        if (!android::base::SetProperty("sys.audio.restart.hal", "1")) {
+            LOG(ERROR) << "SetProperty failed";
+            return nullptr;
+        }
+        if (!mDeathHandler->waitForFired(timeoutMs)) {
+            LOG(ERROR) << "Timeout wait for death";
+            return nullptr;
+        }
+        mDeathHandler.reset();
+        return connectToService(mServiceName);
+    }
+
+  private:
+    class AidlDeathRecipient {
+      public:
+        explicit AidlDeathRecipient(const ndk::SpAIBinder& binder)
+            : binder(binder), recipient(AIBinder_DeathRecipient_new(&binderDiedCallbackAidl)) {}
+
+        binder_status_t linkToDeath() {
+            return AIBinder_linkToDeath(binder.get(), recipient.get(), this);
+        }
+
+        bool waitForFired(std::chrono::milliseconds timeoutMs) {
+            std::unique_lock<std::mutex> lock(mutex);
+            condition.wait_for(lock, timeoutMs, [this]() { return fired; });
+            return fired;
+        }
+
+      private:
+        const ndk::SpAIBinder binder;
+        const ndk::ScopedAIBinder_DeathRecipient recipient;
+        std::mutex mutex;
+        std::condition_variable condition;
+        bool fired = false;
+
+        void binderDied() {
+            std::unique_lock<std::mutex> lock(mutex);
+            fired = true;
+            condition.notify_one();
+        };
+
+        static void binderDiedCallbackAidl(void* cookie) {
+            AidlDeathRecipient* self = static_cast<AidlDeathRecipient*>(cookie);
+            self->binderDied();
+        }
+    };
+
+    std::string mServiceName;
+    ndk::SpAIBinder mBinder;
+    std::unique_ptr<AidlDeathRecipient> mDeathHandler;
+};
diff --git a/audio/aidl/vts/EffectFactoryHelper.h b/audio/aidl/vts/EffectFactoryHelper.h
new file mode 100644
index 0000000..63efae0
--- /dev/null
+++ b/audio/aidl/vts/EffectFactoryHelper.h
@@ -0,0 +1,166 @@
+/*
+ * 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 <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <android/binder_auto_utils.h>
+
+#include "TestUtils.h"
+#include "effect-impl/EffectUUID.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectNullUuid;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::Processing;
+using aidl::android::media::audio::common::AudioUuid;
+
+class EffectFactoryHelper {
+  public:
+    explicit EffectFactoryHelper(const std::string& name) : mServiceName(name) {}
+
+    void ConnectToFactoryService() {
+        mEffectFactory = IFactory::fromBinder(binderUtil.connectToService(mServiceName));
+        ASSERT_NE(mEffectFactory, nullptr);
+    }
+
+    void RestartFactoryService() {
+        ASSERT_NE(mEffectFactory, nullptr);
+        mEffectFactory = IFactory::fromBinder(binderUtil.restartService());
+        ASSERT_NE(mEffectFactory, nullptr);
+        ClearEffectMap();
+    }
+
+    void QueryEffects(const std::optional<AudioUuid>& in_type,
+                      const std::optional<AudioUuid>& in_instance,
+                      std::vector<Descriptor::Identity>* _aidl_return) {
+        ASSERT_NE(mEffectFactory, nullptr);
+        EXPECT_IS_OK(mEffectFactory->queryEffects(in_type, in_instance, _aidl_return));
+        mIds = *_aidl_return;
+    }
+
+    void QueryProcessing(const std::optional<Processing::Type>& in_type,
+                         std::vector<Processing>* _aidl_return) {
+        ASSERT_NE(mEffectFactory, nullptr);
+        EXPECT_IS_OK(mEffectFactory->queryProcessing(in_type, _aidl_return));
+        // only update the whole list if no filter applied
+        if (!in_type.has_value()) {
+            mProcesses = *_aidl_return;
+        }
+    }
+
+    void CreateEffects() {
+        for (const auto& id : mIds) {
+            std::shared_ptr<IEffect> effect;
+            EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
+            EXPECT_NE(effect, nullptr) << id.toString();
+            if (effect) {
+                mEffectIdMap[effect] = id;
+            }
+        }
+    }
+
+    void QueryAndCreateEffects(const AudioUuid& type = EffectNullUuid) {
+        std::vector<Descriptor::Identity> ids;
+        ASSERT_NE(mEffectFactory, nullptr);
+
+        if (type == EffectNullUuid) {
+            EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, &ids));
+        } else {
+            EXPECT_IS_OK(mEffectFactory->queryEffects(type, std::nullopt, &ids));
+        }
+        for (const auto& id : ids) {
+            ASSERT_EQ(id.type, type);
+            std::shared_ptr<IEffect> effect;
+            EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
+            EXPECT_NE(effect, nullptr) << id.toString();
+            if (effect) {
+                mEffectIdMap[effect] = id;
+            }
+        }
+    }
+
+    void CreateEffectsAndExpect(
+            const std::vector<std::pair<Descriptor::Identity, binder_exception_t>>& uuid_status) {
+        ASSERT_NE(mEffectFactory, nullptr);
+        for (const auto& it : uuid_status) {
+            std::shared_ptr<IEffect> effect;
+            auto status = mEffectFactory->createEffect(it.first.uuid, &effect);
+            EXPECT_STATUS(it.second, status);
+            if (effect) {
+                mEffectIdMap[effect] = it.first;
+            }
+        }
+    }
+
+    void DestroyEffectAndExpect(std::shared_ptr<IEffect>& instance, binder_exception_t exception) {
+        ASSERT_NE(mEffectFactory, nullptr);
+        auto status = mEffectFactory->destroyEffect(instance);
+        EXPECT_STATUS(exception, status);
+    }
+
+    void QueryAndCreateAllEffects() {
+        ASSERT_NE(mEffectFactory, nullptr);
+        EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, &mCompleteIds));
+        for (const auto& id : mCompleteIds) {
+            std::shared_ptr<IEffect> effect;
+            EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
+            EXPECT_NE(effect, nullptr) << id.toString();
+            mEffectIdMap[effect] = id;
+        }
+    }
+
+    void DestroyEffects(const binder_exception_t expected = EX_NONE, const int remaining = 0) {
+        ASSERT_NE(mEffectFactory, nullptr);
+
+        for (auto it = mEffectIdMap.begin(); it != mEffectIdMap.end();) {
+            auto erased = it++;
+            auto status = mEffectFactory->destroyEffect(erased->first);
+            EXPECT_STATUS(expected, status);
+            if (status.isOk()) {
+                mEffectIdMap.erase(erased);
+            }
+        }
+        EXPECT_EQ((unsigned int)remaining, mEffectIdMap.size());
+    }
+
+    std::shared_ptr<IFactory> GetFactory() { return mEffectFactory; }
+    const std::vector<Descriptor::Identity>& GetEffectIds() { return mIds; }
+    const std::vector<Descriptor::Identity>& GetCompleteEffectIdList() const {
+        return mCompleteIds;
+    }
+    const std::map<std::shared_ptr<IEffect>, Descriptor::Identity>& GetEffectMap() const {
+        return mEffectIdMap;
+    }
+    void ClearEffectMap() { mEffectIdMap.clear(); }
+
+  private:
+    std::shared_ptr<IFactory> mEffectFactory;
+    std::string mServiceName;
+    AudioHalBinderServiceUtil binderUtil;
+    std::vector<Descriptor::Identity> mIds;
+    std::vector<Descriptor::Identity> mCompleteIds;
+    std::vector<Processing> mProcesses;
+
+    std::map<std::shared_ptr<IEffect>, Descriptor::Identity> mEffectIdMap;
+};
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
new file mode 100644
index 0000000..c58ed13
--- /dev/null
+++ b/audio/aidl/vts/EffectHelper.h
@@ -0,0 +1,310 @@
+/*
+ * 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 <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <aidl/android/media/audio/common/AudioChannelLayout.h>
+#include <aidl/android/media/audio/common/AudioDeviceType.h>
+#include <android/binder_auto_utils.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "AudioHalBinderServiceUtil.h"
+#include "EffectFactoryHelper.h"
+#include "TestUtils.h"
+
+using namespace android;
+using aidl::android::hardware::audio::effect::CommandId;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectNullUuid;
+using aidl::android::hardware::audio::effect::EffectZeroUuid;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::Parameter;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioUuid;
+using aidl::android::media::audio::common::PcmType;
+
+const AudioFormatDescription DefaultFormat = {
+        .type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT, .encoding = ""};
+
+class EffectHelper {
+  public:
+    explicit EffectHelper(const std::string& name) : mFactoryHelper(EffectFactoryHelper(name)) {
+        mFactoryHelper.ConnectToFactoryService();
+    }
+
+    void OpenEffects(const AudioUuid& type = EffectNullUuid) {
+        auto open = [&](const std::shared_ptr<IEffect>& effect) {
+            IEffect::OpenEffectReturn ret;
+            EXPECT_IS_OK(effect->open(mCommon, mSpecific, &ret));
+            EffectParam params;
+            params.statusMQ = std::make_unique<StatusMQ>(ret.statusMQ);
+            params.inputMQ = std::make_unique<DataMQ>(ret.inputDataMQ);
+            params.outputMQ = std::make_unique<DataMQ>(ret.outputDataMQ);
+            mEffectParams.push_back(std::move(params));
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(open, type));
+    }
+
+    void CloseEffects(const binder_status_t status = EX_NONE) {
+        auto close = [&](const std::shared_ptr<IEffect>& effect) {
+            EXPECT_STATUS(status, effect->close());
+        };
+
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
+    }
+
+    void CreateEffects(const int n = 1) {
+        for (int i = 0; i < n; i++) {
+            ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateAllEffects());
+        }
+    }
+
+    void CreateEffectsWithUUID(const AudioUuid& type = EffectNullUuid) {
+        ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateEffects(type));
+    }
+
+    void QueryEffects() { ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateAllEffects()); }
+
+    void DestroyEffects(const binder_status_t status = EX_NONE, const int remaining = 0) {
+        ASSERT_NO_FATAL_FAILURE(mFactoryHelper.DestroyEffects(status, remaining));
+        mEffectDescriptors.clear();
+    }
+
+    void GetEffectDescriptors() {
+        auto get = [&](const std::shared_ptr<IEffect>& effect) {
+            Descriptor desc;
+            EXPECT_IS_OK(effect->getDescriptor(&desc));
+            mEffectDescriptors.push_back(std::move(desc));
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
+    }
+
+    void CommandEffects(CommandId command) {
+        auto close = [&](const std::shared_ptr<IEffect>& effect) {
+            EXPECT_IS_OK(effect->command(command));
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
+    }
+
+    void CommandEffectsExpectStatus(CommandId command, const binder_status_t status) {
+        auto func = [&](const std::shared_ptr<IEffect>& effect) {
+            EXPECT_STATUS(status, effect->command(command));
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
+    }
+
+    void ExpectState(State expected) {
+        auto get = [&](const std::shared_ptr<IEffect>& effect) {
+            State state = State::INIT;
+            EXPECT_IS_OK(effect->getState(&state));
+            EXPECT_EQ(expected, state);
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
+    }
+
+    void SetParameter() {
+        auto func = [&](const std::shared_ptr<IEffect>& effect) {
+            Parameter param;
+            param.set<Parameter::common>(mCommon);
+            EXPECT_IS_OK(effect->setParameter(param));
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
+    }
+
+    void VerifyParameters() {
+        auto func = [&](const std::shared_ptr<IEffect>& effect) {
+            Parameter paramCommonGet = Parameter(), paramCommonExpect = Parameter();
+            Parameter::Id id;
+            id.set<Parameter::Id::commonTag>(0);
+            paramCommonExpect.set<Parameter::common>(mCommon);
+            EXPECT_IS_OK(effect->getParameter(id, &paramCommonGet));
+            EXPECT_EQ(paramCommonExpect, paramCommonGet)
+                    << paramCommonExpect.toString() << " vs " << paramCommonGet.toString();
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
+    }
+
+    void QueryEffects(const std::optional<AudioUuid>& in_type,
+                      const std::optional<AudioUuid>& in_instance,
+                      std::vector<Descriptor::Identity>* _aidl_return) {
+        mFactoryHelper.QueryEffects(in_type, in_instance, _aidl_return);
+    }
+
+    template <typename Functor>
+    void ForEachEffect(Functor functor, const std::optional<AudioUuid>& type = EffectNullUuid) {
+        auto effectMap = mFactoryHelper.GetEffectMap();
+        for (const auto& it : effectMap) {
+            SCOPED_TRACE(it.second.toString());
+            if (type != EffectNullUuid && it.second.type != type) continue;
+            functor(it.first);
+        }
+    }
+
+    template <typename Functor>
+    void ForEachDescriptor(Functor functor) {
+        for (size_t i = 0; i < mEffectDescriptors.size(); i++) {
+            SCOPED_TRACE(mEffectDescriptors[i].toString());
+            functor(i, mEffectDescriptors[i]);
+        }
+    }
+
+    static const size_t mWriteMQSize = 0x400;
+
+    enum class IO : char { INPUT = 0, OUTPUT = 1, INOUT = 2 };
+
+    void initParamCommonFormat(IO io = IO::INOUT,
+                               const AudioFormatDescription& format = DefaultFormat) {
+        if (io == IO::INPUT || io == IO::INOUT) {
+            mCommon.input.base.format = format;
+        }
+        if (io == IO::OUTPUT || io == IO::INOUT) {
+            mCommon.output.base.format = format;
+        }
+    }
+
+    void initParamCommonSampleRate(IO io = IO::INOUT, const int& sampleRate = 48000) {
+        if (io == IO::INPUT || io == IO::INOUT) {
+            mCommon.input.base.sampleRate = sampleRate;
+        }
+        if (io == IO::OUTPUT || io == IO::INOUT) {
+            mCommon.output.base.sampleRate = sampleRate;
+        }
+    }
+
+    void initParamCommonFrameCount(IO io = IO::INOUT, const long& frameCount = 48000) {
+        if (io == IO::INPUT || io == IO::INOUT) {
+            mCommon.input.frameCount = frameCount;
+        }
+        if (io == IO::OUTPUT || io == IO::INOUT) {
+            mCommon.output.frameCount = frameCount;
+        }
+    }
+    void initParamCommon(int session = -1, int ioHandle = -1, int iSampleRate = 48000,
+                         int oSampleRate = 48000, long iFrameCount = 0x100,
+                         long oFrameCount = 0x100) {
+        mCommon.session = session;
+        mCommon.ioHandle = ioHandle;
+
+        auto& input = mCommon.input;
+        auto& output = mCommon.output;
+        input.base.sampleRate = iSampleRate;
+        input.base.channelMask = mInputChannelLayout;
+        input.frameCount = iFrameCount;
+        output.base.sampleRate = oSampleRate;
+        output.base.channelMask = mOutputChannelLayout;
+        output.frameCount = oFrameCount;
+        inputFrameSize = android::hardware::audio::common::getFrameSizeInBytes(
+                input.base.format, input.base.channelMask);
+        outputFrameSize = android::hardware::audio::common::getFrameSizeInBytes(
+                output.base.format, output.base.channelMask);
+    }
+
+    void setSpecific(Parameter::Specific& specific) { mSpecific = specific; }
+
+    // usually this function only call once.
+    void PrepareInputData(size_t s = mWriteMQSize) {
+        size_t maxInputSize = s;
+        for (auto& it : mEffectParams) {
+            auto& mq = it.inputMQ;
+            EXPECT_NE(nullptr, mq);
+            EXPECT_TRUE(mq->isValid());
+            const size_t bytesToWrite = mq->availableToWrite();
+            EXPECT_EQ(inputFrameSize * mCommon.input.frameCount, bytesToWrite);
+            EXPECT_NE(0UL, bytesToWrite);
+            EXPECT_TRUE(s <= bytesToWrite);
+            maxInputSize = std::max(maxInputSize, bytesToWrite);
+        }
+        mInputBuffer.resize(maxInputSize);
+        std::fill(mInputBuffer.begin(), mInputBuffer.end(), 0x5a);
+    }
+
+    void writeToFmq(size_t s = mWriteMQSize) {
+        for (auto& it : mEffectParams) {
+            auto& mq = it.inputMQ;
+            EXPECT_NE(nullptr, mq);
+            const size_t bytesToWrite = mq->availableToWrite();
+            EXPECT_NE(0Ul, bytesToWrite);
+            EXPECT_TRUE(s <= bytesToWrite);
+            EXPECT_TRUE(mq->write(mInputBuffer.data(), s));
+        }
+    }
+
+    void readFromFmq(size_t expectSize = mWriteMQSize) {
+        for (auto& it : mEffectParams) {
+            IEffect::Status status{};
+            auto& statusMq = it.statusMQ;
+            EXPECT_NE(nullptr, statusMq);
+            EXPECT_TRUE(statusMq->readBlocking(&status, 1));
+            EXPECT_EQ(STATUS_OK, status.status);
+            EXPECT_EQ(expectSize, (unsigned)status.fmqByteProduced);
+
+            auto& outputMq = it.outputMQ;
+            EXPECT_NE(nullptr, outputMq);
+            EXPECT_EQ(expectSize, outputMq->availableToRead());
+        }
+    }
+
+    void setInputChannelLayout(AudioChannelLayout input) { mInputChannelLayout = input; }
+    void setOutputChannelLayout(AudioChannelLayout output) { mOutputChannelLayout = output; }
+    const std::vector<Descriptor::Identity>& GetCompleteEffectIdList() const {
+        return mFactoryHelper.GetCompleteEffectIdList();
+    }
+    const std::vector<Descriptor>& getDescriptorVec() const { return mEffectDescriptors; }
+
+  private:
+    EffectFactoryHelper mFactoryHelper;
+
+    AudioChannelLayout mInputChannelLayout =
+            AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                    AudioChannelLayout::LAYOUT_STEREO);
+    AudioChannelLayout mOutputChannelLayout =
+            AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                    AudioChannelLayout::LAYOUT_STEREO);
+
+    Parameter::Common mCommon;
+    Parameter::Specific mSpecific;
+
+    size_t inputFrameSize, outputFrameSize;
+    std::vector<int8_t> mInputBuffer;  // reuse same buffer for all effects testing
+
+    typedef ::android::AidlMessageQueue<
+            IEffect::Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+            StatusMQ;
+    typedef ::android::AidlMessageQueue<
+            int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+            DataMQ;
+
+    class EffectParam {
+      public:
+        std::unique_ptr<StatusMQ> statusMQ;
+        std::unique_ptr<DataMQ> inputMQ;
+        std::unique_ptr<DataMQ> outputMQ;
+    };
+    std::vector<EffectParam> mEffectParams;
+    std::vector<Descriptor> mEffectDescriptors;
+};
diff --git a/audio/aidl/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
new file mode 100644
index 0000000..33c5b72
--- /dev/null
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -0,0 +1,390 @@
+/*
+ * 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 <algorithm>
+#include <chrono>
+
+#include <Utils.h>
+#include <aidl/android/media/audio/common/AudioIoFlags.h>
+#include <aidl/android/media/audio/common/AudioOutputFlags.h>
+
+#include "ModuleConfig.h"
+
+using namespace android;
+using namespace std::chrono_literals;
+
+using aidl::android::hardware::audio::core::IModule;
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioEncapsulationMode;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::AudioOutputFlags;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioProfile;
+using aidl::android::media::audio::common::AudioUsage;
+using aidl::android::media::audio::common::Int;
+using android::hardware::audio::common::isBitPositionFlagSet;
+
+// static
+std::optional<AudioOffloadInfo> ModuleConfig::generateOffloadInfoIfNeeded(
+        const AudioPortConfig& portConfig) {
+    if (portConfig.flags.has_value() &&
+        portConfig.flags.value().getTag() == AudioIoFlags::Tag::output &&
+        isBitPositionFlagSet(portConfig.flags.value().get<AudioIoFlags::Tag::output>(),
+                             AudioOutputFlags::COMPRESS_OFFLOAD)) {
+        AudioOffloadInfo offloadInfo;
+        offloadInfo.base.sampleRate = portConfig.sampleRate.value().value;
+        offloadInfo.base.channelMask = portConfig.channelMask.value();
+        offloadInfo.base.format = portConfig.format.value();
+        offloadInfo.bitRatePerSecond = 256;                                // Arbitrary value.
+        offloadInfo.durationUs = std::chrono::microseconds(1min).count();  // Arbitrary value.
+        offloadInfo.usage = AudioUsage::MEDIA;
+        offloadInfo.encapsulationMode = AudioEncapsulationMode::NONE;
+        return offloadInfo;
+    }
+    return {};
+}
+
+template <typename T>
+auto findById(const std::vector<T>& v, int32_t id) {
+    return std::find_if(v.begin(), v.end(), [&](const auto& p) { return p.id == id; });
+}
+
+ModuleConfig::ModuleConfig(IModule* module) {
+    mStatus = module->getAudioPorts(&mPorts);
+    if (!mStatus.isOk()) return;
+    for (const auto& port : mPorts) {
+        if (port.ext.getTag() != AudioPortExt::Tag::device) continue;
+        const auto& devicePort = port.ext.get<AudioPortExt::Tag::device>();
+        if (devicePort.device.type.connection.empty()) {
+            const bool isInput = port.flags.getTag() == AudioIoFlags::Tag::input;
+            // Permanently attached device.
+            if (isInput) {
+                mAttachedSourceDevicePorts.insert(port.id);
+            } else {
+                mAttachedSinkDevicePorts.insert(port.id);
+            }
+        } else if (port.profiles.empty()) {
+            mExternalDevicePorts.insert(port.id);
+        }
+    }
+    if (!mStatus.isOk()) return;
+    mStatus = module->getAudioRoutes(&mRoutes);
+    if (!mStatus.isOk()) return;
+    mStatus = module->getAudioPortConfigs(&mInitialConfigs);
+}
+
+std::vector<AudioPort> ModuleConfig::getAttachedDevicePorts() const {
+    std::vector<AudioPort> result;
+    std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
+        return mAttachedSinkDevicePorts.count(port.id) != 0 ||
+               mAttachedSourceDevicePorts.count(port.id) != 0;
+    });
+    return result;
+}
+
+std::vector<AudioPort> ModuleConfig::getExternalDevicePorts() const {
+    std::vector<AudioPort> result;
+    std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result),
+                 [&](const auto& port) { return mExternalDevicePorts.count(port.id) != 0; });
+    return result;
+}
+
+std::vector<AudioPort> ModuleConfig::getInputMixPorts() const {
+    std::vector<AudioPort> result;
+    std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [](const auto& port) {
+        return port.ext.getTag() == AudioPortExt::Tag::mix &&
+               port.flags.getTag() == AudioIoFlags::Tag::input;
+    });
+    return result;
+}
+
+std::vector<AudioPort> ModuleConfig::getOutputMixPorts() const {
+    std::vector<AudioPort> result;
+    std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [](const auto& port) {
+        return port.ext.getTag() == AudioPortExt::Tag::mix &&
+               port.flags.getTag() == AudioIoFlags::Tag::output;
+    });
+    return result;
+}
+
+std::vector<AudioPort> ModuleConfig::getOffloadMixPorts(bool attachedOnly, bool singlePort) const {
+    std::vector<AudioPort> result;
+    const auto mixPorts = getMixPorts(false /*isInput*/);
+    auto offloadPortIt = mixPorts.begin();
+    while (offloadPortIt != mixPorts.end()) {
+        offloadPortIt = std::find_if(offloadPortIt, mixPorts.end(), [&](const AudioPort& port) {
+            return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
+                                        AudioOutputFlags::COMPRESS_OFFLOAD) &&
+                   (!attachedOnly || !getAttachedSinkDevicesPortsForMixPort(port).empty());
+        });
+        if (offloadPortIt == mixPorts.end()) break;
+        result.push_back(*offloadPortIt++);
+        if (singlePort) break;
+    }
+    return result;
+}
+
+std::vector<AudioPort> ModuleConfig::getAttachedDevicesPortsForMixPort(
+        bool isInput, const AudioPortConfig& mixPortConfig) const {
+    const auto mixPortIt = findById<AudioPort>(mPorts, mixPortConfig.portId);
+    if (mixPortIt != mPorts.end()) {
+        return getAttachedDevicesPortsForMixPort(isInput, *mixPortIt);
+    }
+    return {};
+}
+
+std::vector<AudioPort> ModuleConfig::getAttachedSinkDevicesPortsForMixPort(
+        const AudioPort& mixPort) const {
+    std::vector<AudioPort> result;
+    for (const auto& route : mRoutes) {
+        if (mAttachedSinkDevicePorts.count(route.sinkPortId) != 0 &&
+            std::find(route.sourcePortIds.begin(), route.sourcePortIds.end(), mixPort.id) !=
+                    route.sourcePortIds.end()) {
+            const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
+            if (devicePortIt != mPorts.end()) result.push_back(*devicePortIt);
+        }
+    }
+    return result;
+}
+
+std::vector<AudioPort> ModuleConfig::getAttachedSourceDevicesPortsForMixPort(
+        const AudioPort& mixPort) const {
+    std::vector<AudioPort> result;
+    for (const auto& route : mRoutes) {
+        if (route.sinkPortId == mixPort.id) {
+            for (const auto srcId : route.sourcePortIds) {
+                if (mAttachedSourceDevicePorts.count(srcId) != 0) {
+                    const auto devicePortIt = findById<AudioPort>(mPorts, srcId);
+                    if (devicePortIt != mPorts.end()) result.push_back(*devicePortIt);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+std::optional<AudioPort> ModuleConfig::getSourceMixPortForAttachedDevice() const {
+    for (const auto& route : mRoutes) {
+        if (mAttachedSinkDevicePorts.count(route.sinkPortId) != 0) {
+            const auto mixPortIt = findById<AudioPort>(mPorts, route.sourcePortIds[0]);
+            if (mixPortIt != mPorts.end()) return *mixPortIt;
+        }
+    }
+    return {};
+}
+
+std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getNonRoutableSrcSinkPair(
+        bool isInput) const {
+    const auto mixPorts = getMixPorts(isInput);
+    std::set<std::pair<int32_t, int32_t>> allowedRoutes;
+    for (const auto& route : mRoutes) {
+        for (const auto srcPortId : route.sourcePortIds) {
+            allowedRoutes.emplace(std::make_pair(srcPortId, route.sinkPortId));
+        }
+    }
+    auto make_pair = [isInput](auto& device, auto& mix) {
+        return isInput ? std::make_pair(device, mix) : std::make_pair(mix, device);
+    };
+    for (const auto portId : isInput ? mAttachedSourceDevicePorts : mAttachedSinkDevicePorts) {
+        const auto devicePortIt = findById<AudioPort>(mPorts, portId);
+        if (devicePortIt == mPorts.end()) continue;
+        auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
+        for (const auto& mixPort : mixPorts) {
+            if (std::find(allowedRoutes.begin(), allowedRoutes.end(),
+                          make_pair(portId, mixPort.id)) == allowedRoutes.end()) {
+                auto mixPortConfig = getSingleConfigForMixPort(isInput, mixPort);
+                if (mixPortConfig.has_value()) {
+                    return make_pair(devicePortConfig, mixPortConfig.value());
+                }
+            }
+        }
+    }
+    return {};
+}
+
+std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getRoutableSrcSinkPair(bool isInput) const {
+    if (isInput) {
+        for (const auto& route : mRoutes) {
+            auto srcPortIdIt = std::find_if(
+                    route.sourcePortIds.begin(), route.sourcePortIds.end(),
+                    [&](const auto& portId) { return mAttachedSourceDevicePorts.count(portId); });
+            if (srcPortIdIt == route.sourcePortIds.end()) continue;
+            const auto devicePortIt = findById<AudioPort>(mPorts, *srcPortIdIt);
+            const auto mixPortIt = findById<AudioPort>(mPorts, route.sinkPortId);
+            if (devicePortIt == mPorts.end() || mixPortIt == mPorts.end()) continue;
+            auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
+            auto mixPortConfig = getSingleConfigForMixPort(isInput, *mixPortIt);
+            if (!mixPortConfig.has_value()) continue;
+            return std::make_pair(devicePortConfig, mixPortConfig.value());
+        }
+    } else {
+        for (const auto& route : mRoutes) {
+            if (mAttachedSinkDevicePorts.count(route.sinkPortId) == 0) continue;
+            const auto mixPortIt = findById<AudioPort>(mPorts, route.sourcePortIds[0]);
+            const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
+            if (devicePortIt == mPorts.end() || mixPortIt == mPorts.end()) continue;
+            auto mixPortConfig = getSingleConfigForMixPort(isInput, *mixPortIt);
+            auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
+            if (!mixPortConfig.has_value()) continue;
+            return std::make_pair(mixPortConfig.value(), devicePortConfig);
+        }
+    }
+    return {};
+}
+
+std::vector<ModuleConfig::SrcSinkGroup> ModuleConfig::getRoutableSrcSinkGroups(bool isInput) const {
+    std::vector<SrcSinkGroup> result;
+    if (isInput) {
+        for (const auto& route : mRoutes) {
+            std::vector<int32_t> srcPortIds;
+            std::copy_if(route.sourcePortIds.begin(), route.sourcePortIds.end(),
+                         std::back_inserter(srcPortIds), [&](const auto& portId) {
+                             return mAttachedSourceDevicePorts.count(portId);
+                         });
+            if (srcPortIds.empty()) continue;
+            const auto mixPortIt = findById<AudioPort>(mPorts, route.sinkPortId);
+            if (mixPortIt == mPorts.end()) continue;
+            auto mixPortConfig = getSingleConfigForMixPort(isInput, *mixPortIt);
+            if (!mixPortConfig.has_value()) continue;
+            std::vector<SrcSinkPair> pairs;
+            for (const auto srcPortId : srcPortIds) {
+                const auto devicePortIt = findById<AudioPort>(mPorts, srcPortId);
+                if (devicePortIt == mPorts.end()) continue;
+                // Using all configs for every source would be too much.
+                auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
+                pairs.emplace_back(devicePortConfig, mixPortConfig.value());
+            }
+            if (!pairs.empty()) {
+                result.emplace_back(route, std::move(pairs));
+            }
+        }
+    } else {
+        for (const auto& route : mRoutes) {
+            if (mAttachedSinkDevicePorts.count(route.sinkPortId) == 0) continue;
+            const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
+            if (devicePortIt == mPorts.end()) continue;
+            auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
+            std::vector<SrcSinkPair> pairs;
+            for (const auto srcPortId : route.sourcePortIds) {
+                const auto mixPortIt = findById<AudioPort>(mPorts, srcPortId);
+                if (mixPortIt == mPorts.end()) continue;
+                // Using all configs for every source would be too much.
+                auto mixPortConfig = getSingleConfigForMixPort(isInput, *mixPortIt);
+                if (mixPortConfig.has_value()) {
+                    pairs.emplace_back(mixPortConfig.value(), devicePortConfig);
+                }
+            }
+            if (!pairs.empty()) {
+                result.emplace_back(route, std::move(pairs));
+            }
+        }
+    }
+    return result;
+}
+
+std::string ModuleConfig::toString() const {
+    std::string result;
+    result.append("Ports: ");
+    result.append(android::internal::ToString(mPorts));
+    result.append("\nInitial configs: ");
+    result.append(android::internal::ToString(mInitialConfigs));
+    result.append("\nAttached sink device ports: ");
+    result.append(android::internal::ToString(mAttachedSinkDevicePorts));
+    result.append("\nAttached source device ports: ");
+    result.append(android::internal::ToString(mAttachedSourceDevicePorts));
+    result.append("\nExternal device ports: ");
+    result.append(android::internal::ToString(mExternalDevicePorts));
+    result.append("\nRoutes: ");
+    result.append(android::internal::ToString(mRoutes));
+    return result;
+}
+
+static size_t combineAudioConfigs(const AudioPort& port, const AudioProfile& profile,
+                                  std::vector<AudioPortConfig>* result) {
+    const size_t newConfigCount = profile.channelMasks.size() * profile.sampleRates.size();
+    result->reserve(result->capacity() + newConfigCount);
+    for (auto channelMask : profile.channelMasks) {
+        for (auto sampleRate : profile.sampleRates) {
+            AudioPortConfig config{};
+            config.portId = port.id;
+            Int sr;
+            sr.value = sampleRate;
+            config.sampleRate = sr;
+            config.channelMask = channelMask;
+            config.format = profile.format;
+            config.flags = port.flags;
+            config.ext = port.ext;
+            result->push_back(std::move(config));
+        }
+    }
+    return newConfigCount;
+}
+
+static bool isDynamicProfile(const AudioProfile& profile) {
+    return (profile.format.type == AudioFormatType::DEFAULT && profile.format.encoding.empty()) ||
+           profile.sampleRates.empty() || profile.channelMasks.empty();
+}
+
+std::vector<AudioPortConfig> ModuleConfig::generateAudioMixPortConfigs(
+        const std::vector<AudioPort>& ports, bool isInput, bool singleProfile) const {
+    std::vector<AudioPortConfig> result;
+    for (const auto& mixPort : ports) {
+        if (getAttachedDevicesPortsForMixPort(isInput, mixPort).empty()) {
+            continue;
+        }
+        for (const auto& profile : mixPort.profiles) {
+            if (isDynamicProfile(profile)) continue;
+            combineAudioConfigs(mixPort, profile, &result);
+            if (singleProfile && !result.empty()) {
+                result.resize(1);
+                return result;
+            }
+        }
+    }
+    return result;
+}
+
+std::vector<AudioPortConfig> ModuleConfig::generateAudioDevicePortConfigs(
+        const std::vector<AudioPort>& ports, bool singleProfile) const {
+    std::vector<AudioPortConfig> result;
+    for (const auto& devicePort : ports) {
+        const size_t resultSizeBefore = result.size();
+        for (const auto& profile : devicePort.profiles) {
+            combineAudioConfigs(devicePort, profile, &result);
+            if (singleProfile && !result.empty()) {
+                result.resize(1);
+                return result;
+            }
+        }
+        if (resultSizeBefore == result.size()) {
+            std::copy_if(mInitialConfigs.begin(), mInitialConfigs.end(), std::back_inserter(result),
+                         [&](const auto& config) { return config.portId == devicePort.id; });
+            if (resultSizeBefore == result.size()) {
+                AudioPortConfig empty;
+                empty.portId = devicePort.id;
+                empty.ext = devicePort.ext;
+                result.push_back(empty);
+            }
+        }
+        if (singleProfile) return result;
+    }
+    return result;
+}
diff --git a/audio/aidl/vts/ModuleConfig.h b/audio/aidl/vts/ModuleConfig.h
new file mode 100644
index 0000000..dc109a7
--- /dev/null
+++ b/audio/aidl/vts/ModuleConfig.h
@@ -0,0 +1,144 @@
+/*
+ * 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 <set>
+#include <utility>
+#include <vector>
+
+#include <aidl/android/hardware/audio/core/AudioRoute.h>
+#include <aidl/android/hardware/audio/core/IModule.h>
+#include <aidl/android/media/audio/common/AudioOffloadInfo.h>
+#include <aidl/android/media/audio/common/AudioPort.h>
+
+class ModuleConfig {
+  public:
+    using SrcSinkPair = std::pair<aidl::android::media::audio::common::AudioPortConfig,
+                                  aidl::android::media::audio::common::AudioPortConfig>;
+    using SrcSinkGroup =
+            std::pair<aidl::android::hardware::audio::core::AudioRoute, std::vector<SrcSinkPair>>;
+
+    static std::optional<aidl::android::media::audio::common::AudioOffloadInfo>
+    generateOffloadInfoIfNeeded(
+            const aidl::android::media::audio::common::AudioPortConfig& portConfig);
+
+    explicit ModuleConfig(aidl::android::hardware::audio::core::IModule* module);
+    const ndk::ScopedAStatus& getStatus() const { return mStatus; }
+    std::string getError() const { return mStatus.getMessage(); }
+
+    std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicePorts() const;
+    std::vector<aidl::android::media::audio::common::AudioPort> getExternalDevicePorts() const;
+    std::vector<aidl::android::media::audio::common::AudioPort> getInputMixPorts() const;
+    std::vector<aidl::android::media::audio::common::AudioPort> getOutputMixPorts() const;
+    std::vector<aidl::android::media::audio::common::AudioPort> getMixPorts(bool isInput) const {
+        return isInput ? getInputMixPorts() : getOutputMixPorts();
+    }
+    std::vector<aidl::android::media::audio::common::AudioPort> getOffloadMixPorts(
+            bool attachedOnly, bool singlePort) const;
+
+    std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicesPortsForMixPort(
+            bool isInput, const aidl::android::media::audio::common::AudioPort& mixPort) const {
+        return isInput ? getAttachedSourceDevicesPortsForMixPort(mixPort)
+                       : getAttachedSinkDevicesPortsForMixPort(mixPort);
+    }
+    std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicesPortsForMixPort(
+            bool isInput,
+            const aidl::android::media::audio::common::AudioPortConfig& mixPortConfig) const;
+    std::vector<aidl::android::media::audio::common::AudioPort>
+    getAttachedSinkDevicesPortsForMixPort(
+            const aidl::android::media::audio::common::AudioPort& mixPort) const;
+    std::vector<aidl::android::media::audio::common::AudioPort>
+    getAttachedSourceDevicesPortsForMixPort(
+            const aidl::android::media::audio::common::AudioPort& mixPort) const;
+    std::optional<aidl::android::media::audio::common::AudioPort>
+    getSourceMixPortForAttachedDevice() const;
+
+    std::optional<SrcSinkPair> getNonRoutableSrcSinkPair(bool isInput) const;
+    std::optional<SrcSinkPair> getRoutableSrcSinkPair(bool isInput) const;
+    std::vector<SrcSinkGroup> getRoutableSrcSinkGroups(bool isInput) const;
+
+    std::vector<aidl::android::media::audio::common::AudioPortConfig>
+    getPortConfigsForAttachedDevicePorts() const {
+        return generateAudioDevicePortConfigs(getAttachedDevicePorts(), false);
+    }
+    std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts()
+            const {
+        auto inputs = generateAudioMixPortConfigs(getInputMixPorts(), true, false);
+        auto outputs = generateAudioMixPortConfigs(getOutputMixPorts(), false, false);
+        inputs.insert(inputs.end(), outputs.begin(), outputs.end());
+        return inputs;
+    }
+    std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
+            bool isInput) const {
+        return generateAudioMixPortConfigs(getMixPorts(isInput), isInput, false);
+    }
+    std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
+            bool isInput, const aidl::android::media::audio::common::AudioPort& port) const {
+        return generateAudioMixPortConfigs({port}, isInput, false);
+    }
+    std::optional<aidl::android::media::audio::common::AudioPortConfig> getSingleConfigForMixPort(
+            bool isInput) const {
+        const auto config = generateAudioMixPortConfigs(getMixPorts(isInput), isInput, true);
+        if (!config.empty()) {
+            return *config.begin();
+        }
+        return {};
+    }
+    std::optional<aidl::android::media::audio::common::AudioPortConfig> getSingleConfigForMixPort(
+            bool isInput, const aidl::android::media::audio::common::AudioPort& port) const {
+        const auto config = generateAudioMixPortConfigs({port}, isInput, true);
+        if (!config.empty()) {
+            return *config.begin();
+        }
+        return {};
+    }
+
+    std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForDevicePort(
+            const aidl::android::media::audio::common::AudioPort& port) const {
+        return generateAudioDevicePortConfigs({port}, false);
+    }
+    aidl::android::media::audio::common::AudioPortConfig getSingleConfigForDevicePort(
+            const aidl::android::media::audio::common::AudioPort& port) const {
+        const auto config = generateAudioDevicePortConfigs({port}, true);
+        return *config.begin();
+    }
+
+    std::string toString() const;
+
+  private:
+    std::vector<aidl::android::media::audio::common::AudioPortConfig> generateAudioMixPortConfigs(
+            const std::vector<aidl::android::media::audio::common::AudioPort>& ports, bool isInput,
+            bool singleProfile) const;
+
+    // Unlike MixPorts, the generator for DevicePorts always returns a non-empty
+    // vector for a non-empty input port list. If there are no profiles in the
+    // port, its initial configs are looked up, if there are none,
+    // then an empty config is used, assuming further negotiation via setAudioPortConfig.
+    std::vector<aidl::android::media::audio::common::AudioPortConfig>
+    generateAudioDevicePortConfigs(
+            const std::vector<aidl::android::media::audio::common::AudioPort>& ports,
+            bool singleProfile) const;
+
+    ndk::ScopedAStatus mStatus = ndk::ScopedAStatus::ok();
+    std::vector<aidl::android::media::audio::common::AudioPort> mPorts;
+    std::vector<aidl::android::media::audio::common::AudioPortConfig> mInitialConfigs;
+    std::set<int32_t> mAttachedSinkDevicePorts;
+    std::set<int32_t> mAttachedSourceDevicePorts;
+    std::set<int32_t> mExternalDevicePorts;
+    std::vector<aidl::android::hardware::audio::core::AudioRoute> mRoutes;
+};
diff --git a/audio/aidl/vts/TestUtils.h b/audio/aidl/vts/TestUtils.h
new file mode 100644
index 0000000..2fc109a
--- /dev/null
+++ b/audio/aidl/vts/TestUtils.h
@@ -0,0 +1,73 @@
+/*
+ * 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 <iostream>
+
+#include <android/binder_auto_utils.h>
+#include <gtest/gtest_pred_impl.h>
+
+namespace ndk {
+
+std::ostream& operator<<(std::ostream& str, const ScopedAStatus& status) {
+    str << status.getDescription();
+    return str;
+}
+
+}  // namespace ndk
+
+namespace android::hardware::audio::common::testing {
+
+namespace detail {
+
+inline ::testing::AssertionResult assertIsOk(const char* expr, const ::ndk::ScopedAStatus& status) {
+    if (status.isOk()) {
+        return ::testing::AssertionSuccess();
+    }
+    return ::testing::AssertionFailure()
+           << "Expected the transaction \'" << expr << "\' to succeed\n"
+           << "  but it has failed with: " << status;
+}
+
+inline ::testing::AssertionResult assertResult(const char* exp_expr, const char* act_expr,
+                                               int32_t expected,
+                                               const ::ndk::ScopedAStatus& status) {
+    if (status.getExceptionCode() == expected) {
+        return ::testing::AssertionSuccess();
+    }
+    return ::testing::AssertionFailure()
+           << "Expected the transaction \'" << act_expr << "\' to fail with " << exp_expr
+           << "\n  but is has completed with: " << status;
+}
+
+}  // namespace detail
+
+}  // namespace android::hardware::audio::common::testing
+
+// Test that the transaction status 'isOk'
+#define ASSERT_IS_OK(ret) \
+    ASSERT_PRED_FORMAT1(::android::hardware::audio::common::testing::detail::assertIsOk, ret)
+#define EXPECT_IS_OK(ret) \
+    EXPECT_PRED_FORMAT1(::android::hardware::audio::common::testing::detail::assertIsOk, ret)
+
+// Test that the transaction status is as expected.
+#define ASSERT_STATUS(expected, ret)                                                       \
+    ASSERT_PRED_FORMAT2(::android::hardware::audio::common::testing::detail::assertResult, \
+                        expected, ret)
+#define EXPECT_STATUS(expected, ret)                                                       \
+    EXPECT_PRED_FORMAT2(::android::hardware::audio::common::testing::detail::assertResult, \
+                        expected, ret)
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
new file mode 100644
index 0000000..2381200
--- /dev/null
+++ b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
@@ -0,0 +1,1734 @@
+/*
+ * 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 <algorithm>
+#include <limits>
+#include <memory>
+#include <optional>
+#include <set>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "VtsHalAudioCore"
+#include <android-base/logging.h>
+
+#include <StreamWorker.h>
+#include <Utils.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/audio/core/IConfig.h>
+#include <aidl/android/hardware/audio/core/IModule.h>
+#include <aidl/android/media/audio/common/AudioIoFlags.h>
+#include <aidl/android/media/audio/common/AudioOutputFlags.h>
+#include <android-base/chrono_utils.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "AudioHalBinderServiceUtil.h"
+#include "ModuleConfig.h"
+#include "TestUtils.h"
+
+using namespace android;
+using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
+using aidl::android::hardware::audio::common::RecordTrackMetadata;
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::hardware::audio::core::AudioPatch;
+using aidl::android::hardware::audio::core::AudioRoute;
+using aidl::android::hardware::audio::core::IModule;
+using aidl::android::hardware::audio::core::IStreamIn;
+using aidl::android::hardware::audio::core::IStreamOut;
+using aidl::android::hardware::audio::core::ModuleDebug;
+using aidl::android::hardware::audio::core::StreamDescriptor;
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using aidl::android::media::audio::common::AudioContentType;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioOutputFlags;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::AudioPortDeviceExt;
+using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::AudioUsage;
+using android::hardware::audio::common::isBitPositionFlagSet;
+using android::hardware::audio::common::StreamLogic;
+using android::hardware::audio::common::StreamWorker;
+using ndk::ScopedAStatus;
+
+template <typename T>
+auto findById(std::vector<T>& v, int32_t id) {
+    return std::find_if(v.begin(), v.end(), [&](const auto& e) { return e.id == id; });
+}
+
+template <typename C>
+std::vector<int32_t> GetNonExistentIds(const C& allIds) {
+    if (allIds.empty()) {
+        return std::vector<int32_t>{-1, 0, 1};
+    }
+    std::vector<int32_t> nonExistentIds;
+    nonExistentIds.push_back(*std::min_element(allIds.begin(), allIds.end()) - 1);
+    nonExistentIds.push_back(*std::max_element(allIds.begin(), allIds.end()) + 1);
+    return nonExistentIds;
+}
+
+AudioDeviceAddress GenerateUniqueDeviceAddress() {
+    static int nextId = 1;
+    // TODO: Use connection-specific ID.
+    return AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(std::to_string(++nextId));
+}
+
+// All 'With*' classes are move-only because they are associated with some
+// resource or state of a HAL module.
+class WithDebugFlags {
+  public:
+    static WithDebugFlags createNested(const WithDebugFlags& parent) {
+        return WithDebugFlags(parent.mFlags);
+    }
+
+    WithDebugFlags() {}
+    explicit WithDebugFlags(const ModuleDebug& initial) : mInitial(initial), mFlags(initial) {}
+    WithDebugFlags(const WithDebugFlags&) = delete;
+    WithDebugFlags& operator=(const WithDebugFlags&) = delete;
+    ~WithDebugFlags() {
+        if (mModule != nullptr) {
+            EXPECT_IS_OK(mModule->setModuleDebug(mInitial));
+        }
+    }
+    void SetUp(IModule* module) { ASSERT_IS_OK(module->setModuleDebug(mFlags)); }
+    ModuleDebug& flags() { return mFlags; }
+
+  private:
+    ModuleDebug mInitial;
+    ModuleDebug mFlags;
+    IModule* mModule = nullptr;
+};
+
+// For consistency, WithAudioPortConfig can start both with a non-existent
+// port config, and with an existing one. Existence is determined by the
+// id of the provided config. If it's not 0, then WithAudioPortConfig is
+// essentially a no-op wrapper.
+class WithAudioPortConfig {
+  public:
+    WithAudioPortConfig() {}
+    explicit WithAudioPortConfig(const AudioPortConfig& config) : mInitialConfig(config) {}
+    WithAudioPortConfig(const WithAudioPortConfig&) = delete;
+    WithAudioPortConfig& operator=(const WithAudioPortConfig&) = delete;
+    ~WithAudioPortConfig() {
+        if (mModule != nullptr) {
+            EXPECT_IS_OK(mModule->resetAudioPortConfig(getId())) << "port config id " << getId();
+        }
+    }
+    void SetUp(IModule* module) {
+        ASSERT_NE(AudioPortExt::Tag::unspecified, mInitialConfig.ext.getTag())
+                << "config: " << mInitialConfig.toString();
+        // Negotiation is allowed for device ports because the HAL module is
+        // allowed to provide an empty profiles list for attached devices.
+        ASSERT_NO_FATAL_FAILURE(
+                SetUpImpl(module, mInitialConfig.ext.getTag() == AudioPortExt::Tag::device));
+    }
+    int32_t getId() const { return mConfig.id; }
+    const AudioPortConfig& get() const { return mConfig; }
+
+  private:
+    void SetUpImpl(IModule* module, bool negotiate) {
+        if (mInitialConfig.id == 0) {
+            AudioPortConfig suggested;
+            bool applied = false;
+            ASSERT_IS_OK(module->setAudioPortConfig(mInitialConfig, &suggested, &applied))
+                    << "Config: " << mInitialConfig.toString();
+            if (!applied && negotiate) {
+                mInitialConfig = suggested;
+                ASSERT_NO_FATAL_FAILURE(SetUpImpl(module, false))
+                        << " while applying suggested config: " << suggested.toString();
+            } else {
+                ASSERT_TRUE(applied) << "Suggested: " << suggested.toString();
+                mConfig = suggested;
+                mModule = module;
+            }
+        } else {
+            mConfig = mInitialConfig;
+        }
+    }
+
+    AudioPortConfig mInitialConfig;
+    IModule* mModule = nullptr;
+    AudioPortConfig mConfig;
+};
+
+class AudioCoreModule : public testing::TestWithParam<std::string> {
+  public:
+    // The default buffer size is used mostly for negative tests.
+    static constexpr int kDefaultBufferSizeFrames = 256;
+
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(ConnectToService());
+        debug.flags().simulateDeviceConnections = true;
+        ASSERT_NO_FATAL_FAILURE(debug.SetUp(module.get()));
+    }
+
+    void TearDown() override {
+        if (module != nullptr) {
+            EXPECT_IS_OK(module->setModuleDebug(ModuleDebug{}));
+        }
+    }
+
+    void ConnectToService() {
+        module = IModule::fromBinder(binderUtil.connectToService(GetParam()));
+        ASSERT_NE(module, nullptr);
+    }
+
+    void RestartService() {
+        ASSERT_NE(module, nullptr);
+        moduleConfig.reset();
+        module = IModule::fromBinder(binderUtil.restartService());
+        ASSERT_NE(module, nullptr);
+    }
+
+    void ApplyEveryConfig(const std::vector<AudioPortConfig>& configs) {
+        for (const auto& config : configs) {
+            ASSERT_NE(0, config.portId);
+            WithAudioPortConfig portConfig(config);
+            ASSERT_NO_FATAL_FAILURE(portConfig.SetUp(module.get()));  // calls setAudioPortConfig
+            EXPECT_EQ(config.portId, portConfig.get().portId);
+            std::vector<AudioPortConfig> retrievedPortConfigs;
+            ASSERT_IS_OK(module->getAudioPortConfigs(&retrievedPortConfigs));
+            const int32_t portConfigId = portConfig.getId();
+            auto configIt = std::find_if(
+                    retrievedPortConfigs.begin(), retrievedPortConfigs.end(),
+                    [&portConfigId](const auto& retrConf) { return retrConf.id == portConfigId; });
+            EXPECT_NE(configIt, retrievedPortConfigs.end())
+                    << "Port config id returned by setAudioPortConfig: " << portConfigId
+                    << " is not found in the list returned by getAudioPortConfigs";
+            if (configIt != retrievedPortConfigs.end()) {
+                EXPECT_EQ(portConfig.get(), *configIt)
+                        << "Applied port config returned by setAudioPortConfig: "
+                        << portConfig.get().toString()
+                        << " is not the same as retrieved via getAudioPortConfigs: "
+                        << configIt->toString();
+            }
+        }
+    }
+
+    template <typename Entity>
+    void GetAllEntityIds(std::set<int32_t>* entityIds,
+                         ScopedAStatus (IModule::*getter)(std::vector<Entity>*),
+                         const std::string& errorMessage) {
+        std::vector<Entity> entities;
+        { ASSERT_IS_OK((module.get()->*getter)(&entities)); }
+        std::transform(entities.begin(), entities.end(),
+                       std::inserter(*entityIds, entityIds->begin()),
+                       [](const auto& entity) { return entity.id; });
+        EXPECT_EQ(entities.size(), entityIds->size()) << errorMessage;
+    }
+
+    void GetAllPatchIds(std::set<int32_t>* patchIds) {
+        return GetAllEntityIds<AudioPatch>(
+                patchIds, &IModule::getAudioPatches,
+                "IDs of audio patches returned by IModule.getAudioPatches are not unique");
+    }
+
+    void GetAllPortIds(std::set<int32_t>* portIds) {
+        return GetAllEntityIds<AudioPort>(
+                portIds, &IModule::getAudioPorts,
+                "IDs of audio ports returned by IModule.getAudioPorts are not unique");
+    }
+
+    void GetAllPortConfigIds(std::set<int32_t>* portConfigIds) {
+        return GetAllEntityIds<AudioPortConfig>(
+                portConfigIds, &IModule::getAudioPortConfigs,
+                "IDs of audio port configs returned by IModule.getAudioPortConfigs are not unique");
+    }
+
+    void SetUpModuleConfig() {
+        if (moduleConfig == nullptr) {
+            moduleConfig = std::make_unique<ModuleConfig>(module.get());
+            ASSERT_EQ(EX_NONE, moduleConfig->getStatus().getExceptionCode())
+                    << "ModuleConfig init error: " << moduleConfig->getError();
+        }
+    }
+
+    std::shared_ptr<IModule> module;
+    std::unique_ptr<ModuleConfig> moduleConfig;
+    AudioHalBinderServiceUtil binderUtil;
+    WithDebugFlags debug;
+};
+
+class WithDevicePortConnectedState {
+  public:
+    explicit WithDevicePortConnectedState(const AudioPort& idAndData) : mIdAndData(idAndData) {}
+    WithDevicePortConnectedState(const AudioPort& id, const AudioDeviceAddress& address)
+        : mIdAndData(setAudioPortAddress(id, address)) {}
+    WithDevicePortConnectedState(const WithDevicePortConnectedState&) = delete;
+    WithDevicePortConnectedState& operator=(const WithDevicePortConnectedState&) = delete;
+    ~WithDevicePortConnectedState() {
+        if (mModule != nullptr) {
+            EXPECT_IS_OK(mModule->disconnectExternalDevice(getId()))
+                    << "when disconnecting device port ID " << getId();
+        }
+    }
+    void SetUp(IModule* module) {
+        ASSERT_IS_OK(module->connectExternalDevice(mIdAndData, &mConnectedPort))
+                << "when connecting device port ID & data " << mIdAndData.toString();
+        ASSERT_NE(mIdAndData.id, getId())
+                << "ID of the connected port must not be the same as the ID of the template port";
+        mModule = module;
+    }
+    int32_t getId() const { return mConnectedPort.id; }
+    const AudioPort& get() { return mConnectedPort; }
+
+  private:
+    static AudioPort setAudioPortAddress(const AudioPort& id, const AudioDeviceAddress& address) {
+        AudioPort result = id;
+        result.ext.get<AudioPortExt::Tag::device>().device.address = address;
+        return result;
+    }
+
+    const AudioPort mIdAndData;
+    IModule* mModule = nullptr;
+    AudioPort mConnectedPort;
+};
+
+class StreamContext {
+  public:
+    typedef AidlMessageQueue<StreamDescriptor::Command, SynchronizedReadWrite> CommandMQ;
+    typedef AidlMessageQueue<StreamDescriptor::Reply, SynchronizedReadWrite> ReplyMQ;
+    typedef AidlMessageQueue<int8_t, SynchronizedReadWrite> DataMQ;
+
+    explicit StreamContext(const StreamDescriptor& descriptor)
+        : mFrameSizeBytes(descriptor.frameSizeBytes),
+          mCommandMQ(new CommandMQ(descriptor.command)),
+          mReplyMQ(new ReplyMQ(descriptor.reply)),
+          mBufferSizeFrames(descriptor.bufferSizeFrames),
+          mDataMQ(maybeCreateDataMQ(descriptor)) {}
+    void checkIsValid() const {
+        EXPECT_NE(0UL, mFrameSizeBytes);
+        ASSERT_NE(nullptr, mCommandMQ);
+        EXPECT_TRUE(mCommandMQ->isValid());
+        ASSERT_NE(nullptr, mReplyMQ);
+        EXPECT_TRUE(mReplyMQ->isValid());
+        if (mDataMQ != nullptr) {
+            EXPECT_TRUE(mDataMQ->isValid());
+            EXPECT_GE(mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize(),
+                      mFrameSizeBytes * mBufferSizeFrames)
+                    << "Data MQ actual buffer size is "
+                       "less than the buffer size as specified by the descriptor";
+        }
+    }
+    size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
+    size_t getBufferSizeFrames() const { return mBufferSizeFrames; }
+    CommandMQ* getCommandMQ() const { return mCommandMQ.get(); }
+    DataMQ* getDataMQ() const { return mDataMQ.get(); }
+    ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
+
+  private:
+    static std::unique_ptr<DataMQ> maybeCreateDataMQ(const StreamDescriptor& descriptor) {
+        using Tag = StreamDescriptor::AudioBuffer::Tag;
+        if (descriptor.audio.getTag() == Tag::fmq) {
+            return std::make_unique<DataMQ>(descriptor.audio.get<Tag::fmq>());
+        }
+        return nullptr;
+    }
+
+    const size_t mFrameSizeBytes;
+    std::unique_ptr<CommandMQ> mCommandMQ;
+    std::unique_ptr<ReplyMQ> mReplyMQ;
+    const size_t mBufferSizeFrames;
+    std::unique_ptr<DataMQ> mDataMQ;
+};
+
+class StreamCommonLogic : public StreamLogic {
+  public:
+    StreamDescriptor::Position getLastObservablePosition() {
+        std::lock_guard<std::mutex> lock(mLock);
+        return mLastReply.observable;
+    }
+
+  protected:
+    explicit StreamCommonLogic(const StreamContext& context)
+        : mCommandMQ(context.getCommandMQ()),
+          mReplyMQ(context.getReplyMQ()),
+          mDataMQ(context.getDataMQ()),
+          mData(context.getBufferSizeBytes()) {}
+    StreamContext::CommandMQ* getCommandMQ() const { return mCommandMQ; }
+    StreamContext::ReplyMQ* getReplyMQ() const { return mReplyMQ; }
+
+    std::string init() override { return ""; }
+
+    StreamContext::CommandMQ* mCommandMQ;
+    StreamContext::ReplyMQ* mReplyMQ;
+    StreamContext::DataMQ* mDataMQ;
+    std::vector<int8_t> mData;
+    std::mutex mLock;
+    StreamDescriptor::Reply mLastReply GUARDED_BY(mLock);
+};
+
+class StreamReaderLogic : public StreamCommonLogic {
+  public:
+    explicit StreamReaderLogic(const StreamContext& context) : StreamCommonLogic(context) {}
+
+  protected:
+    Status cycle() override {
+        StreamDescriptor::Command command{};
+        command.code = StreamDescriptor::COMMAND_BURST;
+        command.fmqByteCount = mData.size();
+        if (!mCommandMQ->writeBlocking(&command, 1)) {
+            LOG(ERROR) << __func__ << ": writing of command into MQ failed";
+            return Status::ABORT;
+        }
+        StreamDescriptor::Reply reply{};
+        if (!mReplyMQ->readBlocking(&reply, 1)) {
+            LOG(ERROR) << __func__ << ": reading of reply from MQ failed";
+            return Status::ABORT;
+        }
+        if (reply.status != STATUS_OK) {
+            LOG(ERROR) << __func__ << ": received error status: " << statusToString(reply.status);
+            return Status::ABORT;
+        }
+        if (reply.fmqByteCount < 0 || reply.fmqByteCount > command.fmqByteCount) {
+            LOG(ERROR) << __func__
+                       << ": received invalid byte count in the reply: " << reply.fmqByteCount;
+            return Status::ABORT;
+        }
+        {
+            std::lock_guard<std::mutex> lock(mLock);
+            mLastReply = reply;
+        }
+        const size_t readCount = std::min({mDataMQ->availableToRead(),
+                                           static_cast<size_t>(reply.fmqByteCount), mData.size()});
+        if (readCount == 0 || mDataMQ->read(mData.data(), readCount)) {
+            return Status::CONTINUE;
+        }
+        LOG(ERROR) << __func__ << ": reading of " << readCount << " data bytes from MQ failed";
+        return Status::ABORT;
+    }
+};
+using StreamReader = StreamWorker<StreamReaderLogic>;
+
+class StreamWriterLogic : public StreamCommonLogic {
+  public:
+    explicit StreamWriterLogic(const StreamContext& context) : StreamCommonLogic(context) {}
+
+  protected:
+    Status cycle() override {
+        if (!mDataMQ->write(mData.data(), mData.size())) {
+            LOG(ERROR) << __func__ << ": writing of " << mData.size() << " bytes to MQ failed";
+            return Status::ABORT;
+        }
+        StreamDescriptor::Command command{};
+        command.code = StreamDescriptor::COMMAND_BURST;
+        command.fmqByteCount = mData.size();
+        if (!mCommandMQ->writeBlocking(&command, 1)) {
+            LOG(ERROR) << __func__ << ": writing of command into MQ failed";
+            return Status::ABORT;
+        }
+        StreamDescriptor::Reply reply{};
+        if (!mReplyMQ->readBlocking(&reply, 1)) {
+            LOG(ERROR) << __func__ << ": reading of reply from MQ failed";
+            return Status::ABORT;
+        }
+        if (reply.status != STATUS_OK) {
+            LOG(ERROR) << __func__ << ": received error status: " << statusToString(reply.status);
+            return Status::ABORT;
+        }
+        if (reply.fmqByteCount < 0 || reply.fmqByteCount > command.fmqByteCount) {
+            LOG(ERROR) << __func__
+                       << ": received invalid byte count in the reply: " << reply.fmqByteCount;
+            return Status::ABORT;
+        }
+        {
+            std::lock_guard<std::mutex> lock(mLock);
+            mLastReply = reply;
+        }
+        return Status::CONTINUE;
+    }
+};
+using StreamWriter = StreamWorker<StreamWriterLogic>;
+
+template <typename T>
+struct IOTraits {
+    static constexpr bool is_input = std::is_same_v<T, IStreamIn>;
+    using Worker = std::conditional_t<is_input, StreamReader, StreamWriter>;
+};
+
+// A dedicated version to test replies to invalid commands.
+class StreamInvalidCommandLogic : public StreamCommonLogic {
+  public:
+    StreamInvalidCommandLogic(const StreamContext& context,
+                              const std::vector<StreamDescriptor::Command>& commands)
+        : StreamCommonLogic(context), mCommands(commands) {}
+
+    std::vector<std::string> getUnexpectedStatuses() {
+        std::lock_guard<std::mutex> lock(mLock);
+        return mUnexpectedStatuses;
+    }
+
+  protected:
+    Status cycle() override {
+        // Send all commands in one cycle to simplify testing.
+        // Extra logging helps to sort out issues with unexpected HAL behavior.
+        for (const auto& command : mCommands) {
+            LOG(INFO) << __func__ << ": writing command " << command.toString() << " into MQ...";
+            if (!getCommandMQ()->writeBlocking(&command, 1)) {
+                LOG(ERROR) << __func__ << ": writing of command into MQ failed";
+                return Status::ABORT;
+            }
+            StreamDescriptor::Reply reply{};
+            LOG(INFO) << __func__ << ": reading reply for command " << command.toString() << "...";
+            if (!getReplyMQ()->readBlocking(&reply, 1)) {
+                LOG(ERROR) << __func__ << ": reading of reply from MQ failed";
+                return Status::ABORT;
+            }
+            LOG(INFO) << __func__ << ": received status " << statusToString(reply.status)
+                      << " for command " << command.toString();
+            if (reply.status != STATUS_BAD_VALUE) {
+                std::string s = command.toString();
+                s.append(", ").append(statusToString(reply.status));
+                std::lock_guard<std::mutex> lock(mLock);
+                mUnexpectedStatuses.push_back(std::move(s));
+            }
+        };
+        return Status::EXIT;
+    }
+
+  private:
+    const std::vector<StreamDescriptor::Command> mCommands;
+    std::mutex mLock;
+    std::vector<std::string> mUnexpectedStatuses GUARDED_BY(mLock);
+};
+
+template <typename Stream>
+class WithStream {
+  public:
+    WithStream() {}
+    explicit WithStream(const AudioPortConfig& portConfig) : mPortConfig(portConfig) {}
+    WithStream(const WithStream&) = delete;
+    WithStream& operator=(const WithStream&) = delete;
+    ~WithStream() {
+        if (mStream != nullptr) {
+            mContext.reset();
+            EXPECT_IS_OK(mStream->close()) << "port config id " << getPortId();
+        }
+    }
+    void SetUpPortConfig(IModule* module) { ASSERT_NO_FATAL_FAILURE(mPortConfig.SetUp(module)); }
+    ScopedAStatus SetUpNoChecks(IModule* module, long bufferSizeFrames) {
+        return SetUpNoChecks(module, mPortConfig.get(), bufferSizeFrames);
+    }
+    ScopedAStatus SetUpNoChecks(IModule* module, const AudioPortConfig& portConfig,
+                                long bufferSizeFrames);
+    void SetUp(IModule* module, long bufferSizeFrames) {
+        ASSERT_NO_FATAL_FAILURE(SetUpPortConfig(module));
+        ASSERT_IS_OK(SetUpNoChecks(module, bufferSizeFrames)) << "port config id " << getPortId();
+        ASSERT_NE(nullptr, mStream) << "port config id " << getPortId();
+        EXPECT_GE(mDescriptor.bufferSizeFrames, bufferSizeFrames)
+                << "actual buffer size must be no less than requested";
+        mContext.emplace(mDescriptor);
+        ASSERT_NO_FATAL_FAILURE(mContext.value().checkIsValid());
+    }
+    Stream* get() const { return mStream.get(); }
+    const StreamContext* getContext() const { return mContext ? &(mContext.value()) : nullptr; }
+    std::shared_ptr<Stream> getSharedPointer() const { return mStream; }
+    const AudioPortConfig& getPortConfig() const { return mPortConfig.get(); }
+    int32_t getPortId() const { return mPortConfig.getId(); }
+
+  private:
+    WithAudioPortConfig mPortConfig;
+    std::shared_ptr<Stream> mStream;
+    StreamDescriptor mDescriptor;
+    std::optional<StreamContext> mContext;
+};
+
+SinkMetadata GenerateSinkMetadata(const AudioPortConfig& portConfig) {
+    RecordTrackMetadata trackMeta;
+    trackMeta.source = AudioSource::MIC;
+    trackMeta.gain = 1.0;
+    trackMeta.channelMask = portConfig.channelMask.value();
+    SinkMetadata metadata;
+    metadata.tracks.push_back(trackMeta);
+    return metadata;
+}
+
+template <>
+ScopedAStatus WithStream<IStreamIn>::SetUpNoChecks(IModule* module,
+                                                   const AudioPortConfig& portConfig,
+                                                   long bufferSizeFrames) {
+    aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
+    args.portConfigId = portConfig.id;
+    args.sinkMetadata = GenerateSinkMetadata(portConfig);
+    args.bufferSizeFrames = bufferSizeFrames;
+    aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
+    ScopedAStatus status = module->openInputStream(args, &ret);
+    if (status.isOk()) {
+        mStream = std::move(ret.stream);
+        mDescriptor = std::move(ret.desc);
+    }
+    return status;
+}
+
+SourceMetadata GenerateSourceMetadata(const AudioPortConfig& portConfig) {
+    PlaybackTrackMetadata trackMeta;
+    trackMeta.usage = AudioUsage::MEDIA;
+    trackMeta.contentType = AudioContentType::MUSIC;
+    trackMeta.gain = 1.0;
+    trackMeta.channelMask = portConfig.channelMask.value();
+    SourceMetadata metadata;
+    metadata.tracks.push_back(trackMeta);
+    return metadata;
+}
+
+template <>
+ScopedAStatus WithStream<IStreamOut>::SetUpNoChecks(IModule* module,
+                                                    const AudioPortConfig& portConfig,
+                                                    long bufferSizeFrames) {
+    aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
+    args.portConfigId = portConfig.id;
+    args.sourceMetadata = GenerateSourceMetadata(portConfig);
+    args.offloadInfo = ModuleConfig::generateOffloadInfoIfNeeded(portConfig);
+    args.bufferSizeFrames = bufferSizeFrames;
+    aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
+    ScopedAStatus status = module->openOutputStream(args, &ret);
+    if (status.isOk()) {
+        mStream = std::move(ret.stream);
+        mDescriptor = std::move(ret.desc);
+    }
+    return status;
+}
+
+class WithAudioPatch {
+  public:
+    WithAudioPatch() {}
+    WithAudioPatch(const AudioPortConfig& srcPortConfig, const AudioPortConfig& sinkPortConfig)
+        : mSrcPortConfig(srcPortConfig), mSinkPortConfig(sinkPortConfig) {}
+    WithAudioPatch(bool sinkIsCfg1, const AudioPortConfig& portConfig1,
+                   const AudioPortConfig& portConfig2)
+        : mSrcPortConfig(sinkIsCfg1 ? portConfig2 : portConfig1),
+          mSinkPortConfig(sinkIsCfg1 ? portConfig1 : portConfig2) {}
+    WithAudioPatch(const WithAudioPatch&) = delete;
+    WithAudioPatch& operator=(const WithAudioPatch&) = delete;
+    ~WithAudioPatch() {
+        if (mModule != nullptr && mPatch.id != 0) {
+            EXPECT_IS_OK(mModule->resetAudioPatch(mPatch.id)) << "patch id " << getId();
+        }
+    }
+    void SetUpPortConfigs(IModule* module) {
+        ASSERT_NO_FATAL_FAILURE(mSrcPortConfig.SetUp(module));
+        ASSERT_NO_FATAL_FAILURE(mSinkPortConfig.SetUp(module));
+    }
+    ScopedAStatus SetUpNoChecks(IModule* module) {
+        mModule = module;
+        mPatch.sourcePortConfigIds = std::vector<int32_t>{mSrcPortConfig.getId()};
+        mPatch.sinkPortConfigIds = std::vector<int32_t>{mSinkPortConfig.getId()};
+        return mModule->setAudioPatch(mPatch, &mPatch);
+    }
+    void SetUp(IModule* module) {
+        ASSERT_NO_FATAL_FAILURE(SetUpPortConfigs(module));
+        ASSERT_IS_OK(SetUpNoChecks(module)) << "source port config id " << mSrcPortConfig.getId()
+                                            << "; sink port config id " << mSinkPortConfig.getId();
+        EXPECT_GT(mPatch.minimumStreamBufferSizeFrames, 0) << "patch id " << getId();
+        for (auto latencyMs : mPatch.latenciesMs) {
+            EXPECT_GT(latencyMs, 0) << "patch id " << getId();
+        }
+    }
+    int32_t getId() const { return mPatch.id; }
+    const AudioPatch& get() const { return mPatch; }
+    const AudioPortConfig& getSinkPortConfig() const { return mSinkPortConfig.get(); }
+    const AudioPortConfig& getSrcPortConfig() const { return mSrcPortConfig.get(); }
+    const AudioPortConfig& getPortConfig(bool getSink) const {
+        return getSink ? getSinkPortConfig() : getSrcPortConfig();
+    }
+
+  private:
+    WithAudioPortConfig mSrcPortConfig;
+    WithAudioPortConfig mSinkPortConfig;
+    IModule* mModule = nullptr;
+    AudioPatch mPatch;
+};
+
+TEST_P(AudioCoreModule, Published) {
+    // SetUp must complete with no failures.
+}
+
+TEST_P(AudioCoreModule, CanBeRestarted) {
+    ASSERT_NO_FATAL_FAILURE(RestartService());
+}
+
+TEST_P(AudioCoreModule, PortIdsAreUnique) {
+    std::set<int32_t> portIds;
+    ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
+}
+
+TEST_P(AudioCoreModule, GetAudioPortsIsStable) {
+    std::vector<AudioPort> ports1;
+    ASSERT_IS_OK(module->getAudioPorts(&ports1));
+    std::vector<AudioPort> ports2;
+    ASSERT_IS_OK(module->getAudioPorts(&ports2));
+    ASSERT_EQ(ports1.size(), ports2.size())
+            << "Sizes of audio port arrays do not match across consequent calls to getAudioPorts";
+    std::sort(ports1.begin(), ports1.end());
+    std::sort(ports2.begin(), ports2.end());
+    EXPECT_EQ(ports1, ports2);
+}
+
+TEST_P(AudioCoreModule, GetAudioRoutesIsStable) {
+    std::vector<AudioRoute> routes1;
+    ASSERT_IS_OK(module->getAudioRoutes(&routes1));
+    std::vector<AudioRoute> routes2;
+    ASSERT_IS_OK(module->getAudioRoutes(&routes2));
+    ASSERT_EQ(routes1.size(), routes2.size())
+            << "Sizes of audio route arrays do not match across consequent calls to getAudioRoutes";
+    std::sort(routes1.begin(), routes1.end());
+    std::sort(routes2.begin(), routes2.end());
+    EXPECT_EQ(routes1, routes2);
+}
+
+TEST_P(AudioCoreModule, GetAudioRoutesAreValid) {
+    std::vector<AudioRoute> routes;
+    ASSERT_IS_OK(module->getAudioRoutes(&routes));
+    for (const auto& route : routes) {
+        std::set<int32_t> sources(route.sourcePortIds.begin(), route.sourcePortIds.end());
+        EXPECT_NE(0UL, sources.size())
+                << "empty audio port sinks in the audio route: " << route.toString();
+        EXPECT_EQ(sources.size(), route.sourcePortIds.size())
+                << "IDs of audio port sinks are not unique in the audio route: "
+                << route.toString();
+    }
+}
+
+TEST_P(AudioCoreModule, GetAudioRoutesPortIdsAreValid) {
+    std::set<int32_t> portIds;
+    ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
+    std::vector<AudioRoute> routes;
+    ASSERT_IS_OK(module->getAudioRoutes(&routes));
+    for (const auto& route : routes) {
+        EXPECT_EQ(1UL, portIds.count(route.sinkPortId))
+                << route.sinkPortId << " sink port id is unknown";
+        for (const auto& source : route.sourcePortIds) {
+            EXPECT_EQ(1UL, portIds.count(source)) << source << " source port id is unknown";
+        }
+    }
+}
+
+TEST_P(AudioCoreModule, GetAudioRoutesForAudioPort) {
+    std::set<int32_t> portIds;
+    ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
+    if (portIds.empty()) {
+        GTEST_SKIP() << "No ports in the module.";
+    }
+    for (const auto portId : portIds) {
+        std::vector<AudioRoute> routes;
+        EXPECT_IS_OK(module->getAudioRoutesForAudioPort(portId, &routes));
+        for (const auto& r : routes) {
+            if (r.sinkPortId != portId) {
+                const auto& srcs = r.sourcePortIds;
+                EXPECT_TRUE(std::find(srcs.begin(), srcs.end(), portId) != srcs.end())
+                        << " port ID " << portId << " does not used by the route " << r.toString();
+            }
+        }
+    }
+    for (const auto portId : GetNonExistentIds(portIds)) {
+        std::vector<AudioRoute> routes;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->getAudioRoutesForAudioPort(portId, &routes))
+                << "port ID " << portId;
+    }
+}
+
+TEST_P(AudioCoreModule, CheckDevicePorts) {
+    std::vector<AudioPort> ports;
+    ASSERT_IS_OK(module->getAudioPorts(&ports));
+    std::optional<int32_t> defaultOutput, defaultInput;
+    std::set<AudioDevice> inputs, outputs;
+    const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
+    for (const auto& port : ports) {
+        if (port.ext.getTag() != AudioPortExt::Tag::device) continue;
+        const auto& devicePort = port.ext.get<AudioPortExt::Tag::device>();
+        EXPECT_NE(AudioDeviceType::NONE, devicePort.device.type.type);
+        EXPECT_NE(AudioDeviceType::IN_DEFAULT, devicePort.device.type.type);
+        EXPECT_NE(AudioDeviceType::OUT_DEFAULT, devicePort.device.type.type);
+        if (devicePort.device.type.type > AudioDeviceType::IN_DEFAULT &&
+            devicePort.device.type.type < AudioDeviceType::OUT_DEFAULT) {
+            EXPECT_EQ(AudioIoFlags::Tag::input, port.flags.getTag());
+        } else if (devicePort.device.type.type > AudioDeviceType::OUT_DEFAULT) {
+            EXPECT_EQ(AudioIoFlags::Tag::output, port.flags.getTag());
+        }
+        EXPECT_FALSE((devicePort.flags & defaultDeviceFlag) != 0 &&
+                     !devicePort.device.type.connection.empty())
+                << "Device port " << port.id
+                << " must be permanently attached to be set as default";
+        if ((devicePort.flags & defaultDeviceFlag) != 0) {
+            if (port.flags.getTag() == AudioIoFlags::Tag::output) {
+                EXPECT_FALSE(defaultOutput.has_value())
+                        << "At least two output device ports are declared as default: "
+                        << defaultOutput.value() << " and " << port.id;
+                defaultOutput = port.id;
+                EXPECT_EQ(0UL, outputs.count(devicePort.device))
+                        << "Non-unique output device: " << devicePort.device.toString();
+                outputs.insert(devicePort.device);
+            } else if (port.flags.getTag() == AudioIoFlags::Tag::input) {
+                EXPECT_FALSE(defaultInput.has_value())
+                        << "At least two input device ports are declared as default: "
+                        << defaultInput.value() << " and " << port.id;
+                defaultInput = port.id;
+                EXPECT_EQ(0UL, inputs.count(devicePort.device))
+                        << "Non-unique input device: " << devicePort.device.toString();
+                inputs.insert(devicePort.device);
+            } else {
+                FAIL() << "Invalid AudioIoFlags Tag: " << toString(port.flags.getTag());
+            }
+        }
+    }
+}
+
+TEST_P(AudioCoreModule, CheckMixPorts) {
+    std::vector<AudioPort> ports;
+    ASSERT_IS_OK(module->getAudioPorts(&ports));
+    std::optional<int32_t> primaryMixPort;
+    for (const auto& port : ports) {
+        if (port.ext.getTag() != AudioPortExt::Tag::mix) continue;
+        const auto& mixPort = port.ext.get<AudioPortExt::Tag::mix>();
+        if (port.flags.getTag() == AudioIoFlags::Tag::output &&
+            isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
+                                 AudioOutputFlags::PRIMARY)) {
+            EXPECT_FALSE(primaryMixPort.has_value())
+                    << "At least two mix ports have PRIMARY flag set: " << primaryMixPort.value()
+                    << " and " << port.id;
+            primaryMixPort = port.id;
+            EXPECT_EQ(1, mixPort.maxOpenStreamCount)
+                    << "Primary mix port " << port.id << " can not have maxOpenStreamCount "
+                    << mixPort.maxOpenStreamCount;
+        }
+    }
+}
+
+TEST_P(AudioCoreModule, GetAudioPort) {
+    std::set<int32_t> portIds;
+    ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
+    if (portIds.empty()) {
+        GTEST_SKIP() << "No ports in the module.";
+    }
+    for (const auto portId : portIds) {
+        AudioPort port;
+        EXPECT_IS_OK(module->getAudioPort(portId, &port));
+        EXPECT_EQ(portId, port.id);
+    }
+    for (const auto portId : GetNonExistentIds(portIds)) {
+        AudioPort port;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->getAudioPort(portId, &port))
+                << "port ID " << portId;
+    }
+}
+
+TEST_P(AudioCoreModule, SetUpModuleConfig) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    // Send the module config to logcat to facilitate failures investigation.
+    LOG(INFO) << "SetUpModuleConfig: " << moduleConfig->toString();
+}
+
+// Verify that HAL module reports for a connected device port at least one non-dynamic profile,
+// that is, a profile with actual supported configuration.
+// Note: This test relies on simulation of external device connections by the HAL module.
+TEST_P(AudioCoreModule, GetAudioPortWithExternalDevices) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
+    if (ports.empty()) {
+        GTEST_SKIP() << "No external devices in the module.";
+    }
+    for (const auto& port : ports) {
+        AudioPort portWithData = port;
+        portWithData.ext.get<AudioPortExt::Tag::device>().device.address =
+                GenerateUniqueDeviceAddress();
+        WithDevicePortConnectedState portConnected(portWithData);
+        ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
+        const int32_t connectedPortId = portConnected.getId();
+        ASSERT_NE(portWithData.id, connectedPortId);
+        ASSERT_EQ(portWithData.ext.getTag(), portConnected.get().ext.getTag());
+        EXPECT_EQ(portWithData.ext.get<AudioPortExt::Tag::device>().device,
+                  portConnected.get().ext.get<AudioPortExt::Tag::device>().device);
+        // Verify that 'getAudioPort' and 'getAudioPorts' return the same connected port.
+        AudioPort connectedPort;
+        EXPECT_IS_OK(module->getAudioPort(connectedPortId, &connectedPort))
+                << "port ID " << connectedPortId;
+        EXPECT_EQ(portConnected.get(), connectedPort);
+        const auto& portProfiles = connectedPort.profiles;
+        EXPECT_NE(0UL, portProfiles.size())
+                << "Connected port has no profiles: " << connectedPort.toString();
+        const auto dynamicProfileIt =
+                std::find_if(portProfiles.begin(), portProfiles.end(), [](const auto& profile) {
+                    return profile.format.type == AudioFormatType::DEFAULT;
+                });
+        EXPECT_EQ(portProfiles.end(), dynamicProfileIt) << "Connected port contains dynamic "
+                                                        << "profiles: " << connectedPort.toString();
+
+        std::vector<AudioPort> allPorts;
+        ASSERT_IS_OK(module->getAudioPorts(&allPorts));
+        const auto allPortsIt = findById(allPorts, connectedPortId);
+        EXPECT_NE(allPorts.end(), allPortsIt);
+        if (allPortsIt != allPorts.end()) {
+            EXPECT_EQ(portConnected.get(), *allPortsIt);
+        }
+    }
+}
+
+TEST_P(AudioCoreModule, OpenStreamInvalidPortConfigId) {
+    std::set<int32_t> portConfigIds;
+    ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
+    for (const auto portConfigId : GetNonExistentIds(portConfigIds)) {
+        {
+            aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
+            args.portConfigId = portConfigId;
+            args.bufferSizeFrames = kDefaultBufferSizeFrames;
+            aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
+            EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openInputStream(args, &ret))
+                    << "port config ID " << portConfigId;
+            EXPECT_EQ(nullptr, ret.stream);
+        }
+        {
+            aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
+            args.portConfigId = portConfigId;
+            args.bufferSizeFrames = kDefaultBufferSizeFrames;
+            aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
+            EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openOutputStream(args, &ret))
+                    << "port config ID " << portConfigId;
+            EXPECT_EQ(nullptr, ret.stream);
+        }
+    }
+}
+
+TEST_P(AudioCoreModule, PortConfigIdsAreUnique) {
+    std::set<int32_t> portConfigIds;
+    ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
+}
+
+TEST_P(AudioCoreModule, PortConfigPortIdsAreValid) {
+    std::set<int32_t> portIds;
+    ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
+    std::vector<AudioPortConfig> portConfigs;
+    ASSERT_IS_OK(module->getAudioPortConfigs(&portConfigs));
+    for (const auto& config : portConfigs) {
+        EXPECT_EQ(1UL, portIds.count(config.portId))
+                << config.portId << " port id is unknown, config id " << config.id;
+    }
+}
+
+TEST_P(AudioCoreModule, ResetAudioPortConfigInvalidId) {
+    std::set<int32_t> portConfigIds;
+    ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
+    for (const auto portConfigId : GetNonExistentIds(portConfigIds)) {
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->resetAudioPortConfig(portConfigId))
+                << "port config ID " << portConfigId;
+    }
+}
+
+// Verify that for the audio port configs provided by the HAL after init, resetting
+// the config does not delete it, but brings it back to the initial config.
+TEST_P(AudioCoreModule, ResetAudioPortConfigToInitialValue) {
+    std::vector<AudioPortConfig> portConfigsBefore;
+    ASSERT_IS_OK(module->getAudioPortConfigs(&portConfigsBefore));
+    // TODO: Change port configs according to port profiles.
+    for (const auto& c : portConfigsBefore) {
+        EXPECT_IS_OK(module->resetAudioPortConfig(c.id)) << "port config ID " << c.id;
+    }
+    std::vector<AudioPortConfig> portConfigsAfter;
+    ASSERT_IS_OK(module->getAudioPortConfigs(&portConfigsAfter));
+    for (const auto& c : portConfigsBefore) {
+        auto afterIt = findById<AudioPortConfig>(portConfigsAfter, c.id);
+        EXPECT_NE(portConfigsAfter.end(), afterIt)
+                << " port config ID " << c.id << " was removed by reset";
+        if (afterIt != portConfigsAfter.end()) {
+            EXPECT_EQ(c, *afterIt);
+        }
+    }
+}
+
+TEST_P(AudioCoreModule, SetAudioPortConfigSuggestedConfig) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    auto srcMixPort = moduleConfig->getSourceMixPortForAttachedDevice();
+    if (!srcMixPort.has_value()) {
+        GTEST_SKIP() << "No mix port for attached output devices";
+    }
+    AudioPortConfig portConfig;
+    AudioPortConfig suggestedConfig;
+    portConfig.portId = srcMixPort.value().id;
+    {
+        bool applied = true;
+        ASSERT_IS_OK(module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
+                << "Config: " << portConfig.toString();
+        EXPECT_FALSE(applied);
+    }
+    EXPECT_EQ(0, suggestedConfig.id);
+    EXPECT_TRUE(suggestedConfig.sampleRate.has_value());
+    EXPECT_TRUE(suggestedConfig.channelMask.has_value());
+    EXPECT_TRUE(suggestedConfig.format.has_value());
+    EXPECT_TRUE(suggestedConfig.flags.has_value());
+    WithAudioPortConfig applied(suggestedConfig);
+    ASSERT_NO_FATAL_FAILURE(applied.SetUp(module.get()));
+    const AudioPortConfig& appliedConfig = applied.get();
+    EXPECT_NE(0, appliedConfig.id);
+    EXPECT_TRUE(appliedConfig.sampleRate.has_value());
+    EXPECT_EQ(suggestedConfig.sampleRate.value(), appliedConfig.sampleRate.value());
+    EXPECT_TRUE(appliedConfig.channelMask.has_value());
+    EXPECT_EQ(suggestedConfig.channelMask.value(), appliedConfig.channelMask.value());
+    EXPECT_TRUE(appliedConfig.format.has_value());
+    EXPECT_EQ(suggestedConfig.format.value(), appliedConfig.format.value());
+    EXPECT_TRUE(appliedConfig.flags.has_value());
+    EXPECT_EQ(suggestedConfig.flags.value(), appliedConfig.flags.value());
+}
+
+TEST_P(AudioCoreModule, SetAllAttachedDevicePortConfigs) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    ASSERT_NO_FATAL_FAILURE(ApplyEveryConfig(moduleConfig->getPortConfigsForAttachedDevicePorts()));
+}
+
+// Note: This test relies on simulation of external device connections by the HAL module.
+TEST_P(AudioCoreModule, SetAllExternalDevicePortConfigs) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
+    if (ports.empty()) {
+        GTEST_SKIP() << "No external devices in the module.";
+    }
+    for (const auto& port : ports) {
+        WithDevicePortConnectedState portConnected(port, GenerateUniqueDeviceAddress());
+        ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
+        ASSERT_NO_FATAL_FAILURE(
+                ApplyEveryConfig(moduleConfig->getPortConfigsForDevicePort(portConnected.get())));
+    }
+}
+
+TEST_P(AudioCoreModule, SetAllStaticAudioPortConfigs) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    ASSERT_NO_FATAL_FAILURE(ApplyEveryConfig(moduleConfig->getPortConfigsForMixPorts()));
+}
+
+TEST_P(AudioCoreModule, SetAudioPortConfigInvalidPortId) {
+    std::set<int32_t> portIds;
+    ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
+    for (const auto portId : GetNonExistentIds(portIds)) {
+        AudioPortConfig portConfig, suggestedConfig;
+        bool applied;
+        portConfig.portId = portId;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+                      module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
+                << "port ID " << portId;
+        EXPECT_FALSE(suggestedConfig.format.has_value());
+        EXPECT_FALSE(suggestedConfig.channelMask.has_value());
+        EXPECT_FALSE(suggestedConfig.sampleRate.has_value());
+    }
+}
+
+TEST_P(AudioCoreModule, SetAudioPortConfigInvalidPortConfigId) {
+    std::set<int32_t> portConfigIds;
+    ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
+    for (const auto portConfigId : GetNonExistentIds(portConfigIds)) {
+        AudioPortConfig portConfig, suggestedConfig;
+        bool applied;
+        portConfig.id = portConfigId;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+                      module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
+                << "port config ID " << portConfigId;
+        EXPECT_FALSE(suggestedConfig.format.has_value());
+        EXPECT_FALSE(suggestedConfig.channelMask.has_value());
+        EXPECT_FALSE(suggestedConfig.sampleRate.has_value());
+    }
+}
+
+TEST_P(AudioCoreModule, TryConnectMissingDevice) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
+    if (ports.empty()) {
+        GTEST_SKIP() << "No external devices in the module.";
+    }
+    AudioPort ignored;
+    WithDebugFlags doNotSimulateConnections = WithDebugFlags::createNested(debug);
+    doNotSimulateConnections.flags().simulateDeviceConnections = false;
+    ASSERT_NO_FATAL_FAILURE(doNotSimulateConnections.SetUp(module.get()));
+    for (const auto& port : ports) {
+        AudioPort portWithData = port;
+        portWithData.ext.get<AudioPortExt::Tag::device>().device.address =
+                GenerateUniqueDeviceAddress();
+        EXPECT_STATUS(EX_ILLEGAL_STATE, module->connectExternalDevice(portWithData, &ignored))
+                << "static port " << portWithData.toString();
+    }
+}
+
+TEST_P(AudioCoreModule, TryChangingConnectionSimulationMidway) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
+    if (ports.empty()) {
+        GTEST_SKIP() << "No external devices in the module.";
+    }
+    WithDevicePortConnectedState portConnected(*ports.begin(), GenerateUniqueDeviceAddress());
+    ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
+    ModuleDebug midwayDebugChange = debug.flags();
+    midwayDebugChange.simulateDeviceConnections = false;
+    EXPECT_STATUS(EX_ILLEGAL_STATE, module->setModuleDebug(midwayDebugChange))
+            << "when trying to disable connections simulation while having a connected device";
+}
+
+TEST_P(AudioCoreModule, ConnectDisconnectExternalDeviceInvalidPorts) {
+    AudioPort ignored;
+    std::set<int32_t> portIds;
+    ASSERT_NO_FATAL_FAILURE(GetAllPortIds(&portIds));
+    for (const auto portId : GetNonExistentIds(portIds)) {
+        AudioPort invalidPort;
+        invalidPort.id = portId;
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->connectExternalDevice(invalidPort, &ignored))
+                << "port ID " << portId << ", when setting CONNECTED state";
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(portId))
+                << "port ID " << portId << ", when setting DISCONNECTED state";
+    }
+
+    std::vector<AudioPort> ports;
+    ASSERT_IS_OK(module->getAudioPorts(&ports));
+    for (const auto& port : ports) {
+        if (port.ext.getTag() != AudioPortExt::Tag::device) {
+            EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->connectExternalDevice(port, &ignored))
+                    << "non-device port ID " << port.id << " when setting CONNECTED state";
+            EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(port.id))
+                    << "non-device port ID " << port.id << " when setting DISCONNECTED state";
+        } else {
+            const auto& devicePort = port.ext.get<AudioPortExt::Tag::device>();
+            if (devicePort.device.type.connection.empty()) {
+                EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->connectExternalDevice(port, &ignored))
+                        << "for a permanently attached device port ID " << port.id
+                        << " when setting CONNECTED state";
+                EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(port.id))
+                        << "for a permanently attached device port ID " << port.id
+                        << " when setting DISCONNECTED state";
+            }
+        }
+    }
+}
+
+// Note: This test relies on simulation of external device connections by the HAL module.
+TEST_P(AudioCoreModule, ConnectDisconnectExternalDeviceTwice) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    AudioPort ignored;
+    std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
+    if (ports.empty()) {
+        GTEST_SKIP() << "No external devices in the module.";
+    }
+    for (const auto& port : ports) {
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->disconnectExternalDevice(port.id))
+                << "when disconnecting already disconnected device port ID " << port.id;
+        AudioPort portWithData = port;
+        portWithData.ext.get<AudioPortExt::Tag::device>().device.address =
+                GenerateUniqueDeviceAddress();
+        WithDevicePortConnectedState portConnected(portWithData);
+        ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+                      module->connectExternalDevice(portConnected.get(), &ignored))
+                << "when trying to connect a connected device port "
+                << portConnected.get().toString();
+        EXPECT_STATUS(EX_ILLEGAL_STATE, module->connectExternalDevice(portWithData, &ignored))
+                << "when connecting again the external device "
+                << portWithData.ext.get<AudioPortExt::Tag::device>().device.toString()
+                << "; Returned connected port " << ignored.toString() << " for template "
+                << portWithData.toString();
+    }
+}
+
+// Note: This test relies on simulation of external device connections by the HAL module.
+TEST_P(AudioCoreModule, DisconnectExternalDeviceNonResetPortConfig) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
+    if (ports.empty()) {
+        GTEST_SKIP() << "No external devices in the module.";
+    }
+    for (const auto& port : ports) {
+        WithDevicePortConnectedState portConnected(port, GenerateUniqueDeviceAddress());
+        ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
+        const auto portConfig = moduleConfig->getSingleConfigForDevicePort(portConnected.get());
+        {
+            WithAudioPortConfig config(portConfig);
+            // Note: if SetUp fails, check the status of 'GetAudioPortWithExternalDevices' test.
+            // Our test assumes that 'getAudioPort' returns at least one profile, and it
+            // is not a dynamic profile.
+            ASSERT_NO_FATAL_FAILURE(config.SetUp(module.get()));
+            EXPECT_STATUS(EX_ILLEGAL_STATE, module->disconnectExternalDevice(portConnected.getId()))
+                    << "when trying to disconnect device port ID " << port.id
+                    << " with active configuration " << config.getId();
+        }
+    }
+}
+
+TEST_P(AudioCoreModule, ExternalDevicePortRoutes) {
+    ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
+    if (ports.empty()) {
+        GTEST_SKIP() << "No external devices in the module.";
+    }
+    for (const auto& port : ports) {
+        std::vector<AudioRoute> routesBefore;
+        ASSERT_IS_OK(module->getAudioRoutes(&routesBefore));
+
+        int32_t connectedPortId;
+        {
+            WithDevicePortConnectedState portConnected(port, GenerateUniqueDeviceAddress());
+            ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
+            connectedPortId = portConnected.getId();
+            std::vector<AudioRoute> connectedPortRoutes;
+            ASSERT_IS_OK(module->getAudioRoutesForAudioPort(connectedPortId, &connectedPortRoutes))
+                    << "when retrieving routes for connected port id " << connectedPortId;
+            // There must be routes for the port to be useful.
+            if (connectedPortRoutes.empty()) {
+                std::vector<AudioRoute> allRoutes;
+                ASSERT_IS_OK(module->getAudioRoutes(&allRoutes));
+                ADD_FAILURE() << " no routes returned for the connected port "
+                              << portConnected.get().toString()
+                              << "; all routes: " << android::internal::ToString(allRoutes);
+            }
+        }
+        std::vector<AudioRoute> ignored;
+        ASSERT_STATUS(EX_ILLEGAL_ARGUMENT,
+                      module->getAudioRoutesForAudioPort(connectedPortId, &ignored))
+                << "when retrieving routes for released connected port id " << connectedPortId;
+
+        std::vector<AudioRoute> routesAfter;
+        ASSERT_IS_OK(module->getAudioRoutes(&routesAfter));
+        ASSERT_EQ(routesBefore.size(), routesAfter.size())
+                << "Sizes of audio route arrays do not match after creating and "
+                << "releasing a connected port";
+        std::sort(routesBefore.begin(), routesBefore.end());
+        std::sort(routesAfter.begin(), routesAfter.end());
+        EXPECT_EQ(routesBefore, routesAfter);
+    }
+}
+
+template <typename Stream>
+class AudioStream : public AudioCoreModule {
+  public:
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(AudioCoreModule::SetUp());
+        ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    }
+
+    void CloseTwice() {
+        const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+        if (!portConfig.has_value()) {
+            GTEST_SKIP() << "No mix port for attached devices";
+        }
+        std::shared_ptr<Stream> heldStream;
+        {
+            WithStream<Stream> stream(portConfig.value());
+            ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+            heldStream = stream.getSharedPointer();
+        }
+        EXPECT_STATUS(EX_ILLEGAL_STATE, heldStream->close()) << "when closing the stream twice";
+    }
+
+    void OpenAllConfigs() {
+        const auto allPortConfigs =
+                moduleConfig->getPortConfigsForMixPorts(IOTraits<Stream>::is_input);
+        for (const auto& portConfig : allPortConfigs) {
+            WithStream<Stream> stream(portConfig);
+            ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+        }
+    }
+
+    void OpenInvalidBufferSize() {
+        const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+        if (!portConfig.has_value()) {
+            GTEST_SKIP() << "No mix port for attached devices";
+        }
+        WithStream<Stream> stream(portConfig.value());
+        ASSERT_NO_FATAL_FAILURE(stream.SetUpPortConfig(module.get()));
+        // The buffer size of 1 frame should be impractically small, and thus
+        // less than any minimum buffer size suggested by any HAL.
+        for (long bufferSize : std::array<long, 4>{-1, 0, 1, std::numeric_limits<long>::max()}) {
+            EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, stream.SetUpNoChecks(module.get(), bufferSize))
+                    << "for the buffer size " << bufferSize;
+            EXPECT_EQ(nullptr, stream.get());
+        }
+    }
+
+    void OpenInvalidDirection() {
+        // Important! The direction of the port config must be reversed.
+        const auto portConfig =
+                moduleConfig->getSingleConfigForMixPort(!IOTraits<Stream>::is_input);
+        if (!portConfig.has_value()) {
+            GTEST_SKIP() << "No mix port for attached devices";
+        }
+        WithStream<Stream> stream(portConfig.value());
+        ASSERT_NO_FATAL_FAILURE(stream.SetUpPortConfig(module.get()));
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+                      stream.SetUpNoChecks(module.get(), kDefaultBufferSizeFrames))
+                << "port config ID " << stream.getPortId();
+        EXPECT_EQ(nullptr, stream.get());
+    }
+
+    void OpenOverMaxCount() {
+        constexpr bool isInput = IOTraits<Stream>::is_input;
+        auto ports = moduleConfig->getMixPorts(isInput);
+        bool hasSingleRun = false;
+        for (const auto& port : ports) {
+            const size_t maxStreamCount = port.ext.get<AudioPortExt::Tag::mix>().maxOpenStreamCount;
+            if (maxStreamCount == 0 ||
+                moduleConfig->getAttachedDevicesPortsForMixPort(isInput, port).empty()) {
+                // No restrictions or no permanently attached devices.
+                continue;
+            }
+            auto portConfigs = moduleConfig->getPortConfigsForMixPorts(isInput, port);
+            if (portConfigs.size() < maxStreamCount + 1) {
+                // Not able to open a sufficient number of streams for this port.
+                continue;
+            }
+            hasSingleRun = true;
+            std::optional<WithStream<Stream>> streamWraps[maxStreamCount + 1];
+            for (size_t i = 0; i <= maxStreamCount; ++i) {
+                streamWraps[i].emplace(portConfigs[i]);
+                WithStream<Stream>& stream = streamWraps[i].value();
+                if (i < maxStreamCount) {
+                    ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+                } else {
+                    ASSERT_NO_FATAL_FAILURE(stream.SetUpPortConfig(module.get()));
+                    EXPECT_STATUS(EX_ILLEGAL_STATE,
+                                  stream.SetUpNoChecks(module.get(), kDefaultBufferSizeFrames))
+                            << "port config ID " << stream.getPortId() << ", maxOpenStreamCount is "
+                            << maxStreamCount;
+                }
+            }
+        }
+        if (!hasSingleRun) {
+            GTEST_SKIP() << "Not enough ports to test max open stream count";
+        }
+    }
+
+    void OpenTwiceSamePortConfig() {
+        const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+        if (!portConfig.has_value()) {
+            GTEST_SKIP() << "No mix port for attached devices";
+        }
+        EXPECT_NO_FATAL_FAILURE(OpenTwiceSamePortConfigImpl(portConfig.value()));
+    }
+
+    void ReadOrWrite(bool useSetupSequence2, bool validateObservablePosition) {
+        const auto allPortConfigs =
+                moduleConfig->getPortConfigsForMixPorts(IOTraits<Stream>::is_input);
+        if (allPortConfigs.empty()) {
+            GTEST_SKIP() << "No mix ports have attached devices";
+        }
+        for (const auto& portConfig : allPortConfigs) {
+            EXPECT_NO_FATAL_FAILURE(
+                    ReadOrWriteImpl(portConfig, useSetupSequence2, validateObservablePosition))
+                    << portConfig.toString();
+        }
+    }
+
+    void ResetPortConfigWithOpenStream() {
+        const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+        if (!portConfig.has_value()) {
+            GTEST_SKIP() << "No mix port for attached devices";
+        }
+        WithStream<Stream> stream(portConfig.value());
+        ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+        EXPECT_STATUS(EX_ILLEGAL_STATE, module->resetAudioPortConfig(stream.getPortId()))
+                << "port config ID " << stream.getPortId();
+    }
+
+    void SendInvalidCommand() {
+        const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+        if (!portConfig.has_value()) {
+            GTEST_SKIP() << "No mix port for attached devices";
+        }
+        EXPECT_NO_FATAL_FAILURE(SendInvalidCommandImpl(portConfig.value()));
+    }
+
+    void OpenTwiceSamePortConfigImpl(const AudioPortConfig& portConfig) {
+        WithStream<Stream> stream1(portConfig);
+        ASSERT_NO_FATAL_FAILURE(stream1.SetUp(module.get(), kDefaultBufferSizeFrames));
+        WithStream<Stream> stream2;
+        EXPECT_STATUS(EX_ILLEGAL_STATE, stream2.SetUpNoChecks(module.get(), stream1.getPortConfig(),
+                                                              kDefaultBufferSizeFrames))
+                << "when opening a stream twice for the same port config ID "
+                << stream1.getPortId();
+    }
+
+    template <class Worker>
+    void WaitForObservablePositionAdvance(Worker& worker) {
+        static constexpr int kWriteDurationUs = 50 * 1000;
+        static constexpr std::chrono::milliseconds kPositionChangeTimeout{10000};
+        int64_t framesInitial;
+        framesInitial = worker.getLastObservablePosition().frames;
+        ASSERT_FALSE(worker.hasError());
+        bool timedOut = false;
+        int64_t frames = framesInitial;
+        for (android::base::Timer elapsed;
+             frames <= framesInitial && !worker.hasError() &&
+             !(timedOut = (elapsed.duration() >= kPositionChangeTimeout));) {
+            usleep(kWriteDurationUs);
+            frames = worker.getLastObservablePosition().frames;
+        }
+        EXPECT_FALSE(timedOut);
+        EXPECT_FALSE(worker.hasError()) << worker.getError();
+        EXPECT_GT(frames, framesInitial);
+    }
+
+    void ReadOrWriteImpl(const AudioPortConfig& portConfig, bool useSetupSequence2,
+                         bool validateObservablePosition) {
+        if (!useSetupSequence2) {
+            ASSERT_NO_FATAL_FAILURE(
+                    ReadOrWriteSetupSequence1(portConfig, validateObservablePosition));
+        } else {
+            ASSERT_NO_FATAL_FAILURE(
+                    ReadOrWriteSetupSequence2(portConfig, validateObservablePosition));
+        }
+    }
+
+    // Set up a patch first, then open a stream.
+    void ReadOrWriteSetupSequence1(const AudioPortConfig& portConfig,
+                                   bool validateObservablePosition) {
+        auto devicePorts = moduleConfig->getAttachedDevicesPortsForMixPort(
+                IOTraits<Stream>::is_input, portConfig);
+        ASSERT_FALSE(devicePorts.empty());
+        auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
+        WithAudioPatch patch(IOTraits<Stream>::is_input, portConfig, devicePortConfig);
+        ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+
+        WithStream<Stream> stream(patch.getPortConfig(IOTraits<Stream>::is_input));
+        ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+        typename IOTraits<Stream>::Worker worker(*stream.getContext());
+
+        ASSERT_TRUE(worker.start());
+        ASSERT_TRUE(worker.waitForAtLeastOneCycle());
+        if (validateObservablePosition) {
+            ASSERT_NO_FATAL_FAILURE(WaitForObservablePositionAdvance(worker));
+        }
+    }
+
+    // Open a stream, then set up a patch for it.
+    void ReadOrWriteSetupSequence2(const AudioPortConfig& portConfig,
+                                   bool validateObservablePosition) {
+        WithStream<Stream> stream(portConfig);
+        ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+        typename IOTraits<Stream>::Worker worker(*stream.getContext());
+
+        auto devicePorts = moduleConfig->getAttachedDevicesPortsForMixPort(
+                IOTraits<Stream>::is_input, portConfig);
+        ASSERT_FALSE(devicePorts.empty());
+        auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
+        WithAudioPatch patch(IOTraits<Stream>::is_input, stream.getPortConfig(), devicePortConfig);
+        ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+
+        ASSERT_TRUE(worker.start());
+        ASSERT_TRUE(worker.waitForAtLeastOneCycle());
+        if (validateObservablePosition) {
+            ASSERT_NO_FATAL_FAILURE(WaitForObservablePositionAdvance(worker));
+        }
+    }
+
+    void SendInvalidCommandImpl(const AudioPortConfig& portConfig) {
+        std::vector<StreamDescriptor::Command> commands(6);
+        commands[0].code = -1;
+        commands[1].code = StreamDescriptor::COMMAND_BURST - 1;
+        commands[2].code = std::numeric_limits<int32_t>::min();
+        commands[3].code = std::numeric_limits<int32_t>::max();
+        commands[4].code = StreamDescriptor::COMMAND_BURST;
+        commands[4].fmqByteCount = -1;
+        commands[5].code = StreamDescriptor::COMMAND_BURST;
+        commands[5].fmqByteCount = std::numeric_limits<int32_t>::min();
+        WithStream<Stream> stream(portConfig);
+        ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+        StreamWorker<StreamInvalidCommandLogic> writer(*stream.getContext(), commands);
+        ASSERT_TRUE(writer.start());
+        writer.waitForAtLeastOneCycle();
+        auto unexpectedStatuses = writer.getUnexpectedStatuses();
+        EXPECT_EQ(0UL, unexpectedStatuses.size())
+                << "Pairs of (command, actual status): "
+                << android::internal::ToString(unexpectedStatuses);
+    }
+};
+using AudioStreamIn = AudioStream<IStreamIn>;
+using AudioStreamOut = AudioStream<IStreamOut>;
+
+#define TEST_IO_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_IO_STREAM_2(method_name, arg1, arg2)           \
+    TEST_P(AudioStreamIn, method_name##_##arg1##_##arg2) {  \
+        ASSERT_NO_FATAL_FAILURE(method_name(arg1, arg2));   \
+    }                                                       \
+    TEST_P(AudioStreamOut, method_name##_##arg1##_##arg2) { \
+        ASSERT_NO_FATAL_FAILURE(method_name(arg1, arg2));   \
+    }
+
+TEST_IO_STREAM(CloseTwice);
+TEST_IO_STREAM(OpenAllConfigs);
+TEST_IO_STREAM(OpenInvalidBufferSize);
+TEST_IO_STREAM(OpenInvalidDirection);
+TEST_IO_STREAM(OpenOverMaxCount);
+TEST_IO_STREAM(OpenTwiceSamePortConfig);
+// Use of constants makes comprehensible test names.
+constexpr bool SetupSequence1 = false;
+constexpr bool SetupSequence2 = true;
+constexpr bool SetupOnly = false;
+constexpr bool ValidateObservablePosition = true;
+TEST_IO_STREAM_2(ReadOrWrite, SetupSequence1, SetupOnly);
+TEST_IO_STREAM_2(ReadOrWrite, SetupSequence2, SetupOnly);
+TEST_IO_STREAM_2(ReadOrWrite, SetupSequence1, ValidateObservablePosition);
+TEST_IO_STREAM_2(ReadOrWrite, SetupSequence2, ValidateObservablePosition);
+TEST_IO_STREAM(ResetPortConfigWithOpenStream);
+TEST_IO_STREAM(SendInvalidCommand);
+
+TEST_P(AudioStreamOut, OpenTwicePrimary) {
+    const auto mixPorts = moduleConfig->getMixPorts(false);
+    auto primaryPortIt = std::find_if(mixPorts.begin(), mixPorts.end(), [](const AudioPort& port) {
+        return port.flags.getTag() == AudioIoFlags::Tag::output &&
+               isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
+                                    AudioOutputFlags::PRIMARY);
+    });
+    if (primaryPortIt == mixPorts.end()) {
+        GTEST_SKIP() << "No primary mix port";
+    }
+    if (moduleConfig->getAttachedSinkDevicesPortsForMixPort(*primaryPortIt).empty()) {
+        GTEST_SKIP() << "Primary mix port can not be routed to any of attached devices";
+    }
+    const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, *primaryPortIt);
+    ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for the primary mix port";
+    EXPECT_NO_FATAL_FAILURE(OpenTwiceSamePortConfigImpl(portConfig.value()));
+}
+
+TEST_P(AudioStreamOut, RequireOffloadInfo) {
+    const auto offloadMixPorts =
+            moduleConfig->getOffloadMixPorts(true /*attachedOnly*/, true /*singlePort*/);
+    if (offloadMixPorts.empty()) {
+        GTEST_SKIP()
+                << "No mix port for compressed offload that could be routed to attached devices";
+    }
+    const auto portConfig =
+            moduleConfig->getSingleConfigForMixPort(false, *offloadMixPorts.begin());
+    ASSERT_TRUE(portConfig.has_value())
+            << "No profiles specified for the compressed offload mix port";
+    StreamDescriptor descriptor;
+    std::shared_ptr<IStreamOut> ignored;
+    aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
+    args.portConfigId = portConfig.value().id;
+    args.sourceMetadata = GenerateSourceMetadata(portConfig.value());
+    args.bufferSizeFrames = kDefaultBufferSizeFrames;
+    aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
+    EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openOutputStream(args, &ret))
+            << "when no offload info is provided for a compressed offload mix port";
+}
+
+// Tests specific to audio patches. The fixure class is named 'AudioModulePatch'
+// to avoid clashing with 'AudioPatch' class.
+class AudioModulePatch : public AudioCoreModule {
+  public:
+    static std::string direction(bool isInput, bool capitalize) {
+        return isInput ? (capitalize ? "Input" : "input") : (capitalize ? "Output" : "output");
+    }
+
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(AudioCoreModule::SetUp());
+        ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+    }
+
+    void SetInvalidPatchHelper(int32_t expectedException, const std::vector<int32_t>& sources,
+                               const std::vector<int32_t>& sinks) {
+        AudioPatch patch;
+        patch.sourcePortConfigIds = sources;
+        patch.sinkPortConfigIds = sinks;
+        ASSERT_STATUS(expectedException, module->setAudioPatch(patch, &patch))
+                << "patch source ids: " << android::internal::ToString(sources)
+                << "; sink ids: " << android::internal::ToString(sinks);
+    }
+
+    void ResetPortConfigUsedByPatch(bool isInput) {
+        auto srcSinkGroups = moduleConfig->getRoutableSrcSinkGroups(isInput);
+        if (srcSinkGroups.empty()) {
+            GTEST_SKIP() << "No routes to any attached " << direction(isInput, false) << " devices";
+        }
+        auto srcSinkGroup = *srcSinkGroups.begin();
+        auto srcSink = *srcSinkGroup.second.begin();
+        WithAudioPatch patch(srcSink.first, srcSink.second);
+        ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+        std::vector<int32_t> sourceAndSinkPortConfigIds(patch.get().sourcePortConfigIds);
+        sourceAndSinkPortConfigIds.insert(sourceAndSinkPortConfigIds.end(),
+                                          patch.get().sinkPortConfigIds.begin(),
+                                          patch.get().sinkPortConfigIds.end());
+        for (const auto portConfigId : sourceAndSinkPortConfigIds) {
+            EXPECT_STATUS(EX_ILLEGAL_STATE, module->resetAudioPortConfig(portConfigId))
+                    << "port config ID " << portConfigId;
+        }
+    }
+
+    void SetInvalidPatch(bool isInput) {
+        auto srcSinkPair = moduleConfig->getRoutableSrcSinkPair(isInput);
+        if (!srcSinkPair.has_value()) {
+            GTEST_SKIP() << "No routes to any attached " << direction(isInput, false) << " devices";
+        }
+        WithAudioPortConfig srcPortConfig(srcSinkPair.value().first);
+        ASSERT_NO_FATAL_FAILURE(srcPortConfig.SetUp(module.get()));
+        WithAudioPortConfig sinkPortConfig(srcSinkPair.value().second);
+        ASSERT_NO_FATAL_FAILURE(sinkPortConfig.SetUp(module.get()));
+        {  // Check that the pair can actually be used for setting up a patch.
+            WithAudioPatch patch(srcPortConfig.get(), sinkPortConfig.get());
+            ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+        }
+        EXPECT_NO_FATAL_FAILURE(
+                SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT, {}, {sinkPortConfig.getId()}));
+        EXPECT_NO_FATAL_FAILURE(SetInvalidPatchHelper(
+                EX_ILLEGAL_ARGUMENT, {srcPortConfig.getId(), srcPortConfig.getId()},
+                {sinkPortConfig.getId()}));
+        EXPECT_NO_FATAL_FAILURE(
+                SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT, {srcPortConfig.getId()}, {}));
+        EXPECT_NO_FATAL_FAILURE(
+                SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT, {srcPortConfig.getId()},
+                                      {sinkPortConfig.getId(), sinkPortConfig.getId()}));
+
+        std::set<int32_t> portConfigIds;
+        ASSERT_NO_FATAL_FAILURE(GetAllPortConfigIds(&portConfigIds));
+        for (const auto portConfigId : GetNonExistentIds(portConfigIds)) {
+            EXPECT_NO_FATAL_FAILURE(SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT, {portConfigId},
+                                                          {sinkPortConfig.getId()}));
+            EXPECT_NO_FATAL_FAILURE(SetInvalidPatchHelper(EX_ILLEGAL_ARGUMENT,
+                                                          {srcPortConfig.getId()}, {portConfigId}));
+        }
+    }
+
+    void SetNonRoutablePatch(bool isInput) {
+        auto srcSinkPair = moduleConfig->getNonRoutableSrcSinkPair(isInput);
+        if (!srcSinkPair.has_value()) {
+            GTEST_SKIP() << "All possible source/sink pairs are routable";
+        }
+        WithAudioPatch patch(srcSinkPair.value().first, srcSinkPair.value().second);
+        ASSERT_NO_FATAL_FAILURE(patch.SetUpPortConfigs(module.get()));
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, patch.SetUpNoChecks(module.get()))
+                << "when setting up a patch from " << srcSinkPair.value().first.toString() << " to "
+                << srcSinkPair.value().second.toString() << " that does not have a route";
+    }
+
+    void SetPatch(bool isInput) {
+        auto srcSinkGroups = moduleConfig->getRoutableSrcSinkGroups(isInput);
+        if (srcSinkGroups.empty()) {
+            GTEST_SKIP() << "No routes to any attached " << direction(isInput, false) << " devices";
+        }
+        for (const auto& srcSinkGroup : srcSinkGroups) {
+            const auto& route = srcSinkGroup.first;
+            std::vector<std::unique_ptr<WithAudioPatch>> patches;
+            for (const auto& srcSink : srcSinkGroup.second) {
+                if (!route.isExclusive) {
+                    patches.push_back(
+                            std::make_unique<WithAudioPatch>(srcSink.first, srcSink.second));
+                    EXPECT_NO_FATAL_FAILURE(patches[patches.size() - 1]->SetUp(module.get()));
+                } else {
+                    WithAudioPatch patch(srcSink.first, srcSink.second);
+                    EXPECT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+                }
+            }
+        }
+    }
+
+    void UpdatePatch(bool isInput) {
+        auto srcSinkGroups = moduleConfig->getRoutableSrcSinkGroups(isInput);
+        if (srcSinkGroups.empty()) {
+            GTEST_SKIP() << "No routes to any attached " << direction(isInput, false) << " devices";
+        }
+        for (const auto& srcSinkGroup : srcSinkGroups) {
+            for (const auto& srcSink : srcSinkGroup.second) {
+                WithAudioPatch patch(srcSink.first, srcSink.second);
+                ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+                AudioPatch ignored;
+                EXPECT_NO_FATAL_FAILURE(module->setAudioPatch(patch.get(), &ignored));
+            }
+        }
+    }
+
+    void UpdateInvalidPatchId(bool isInput) {
+        auto srcSinkGroups = moduleConfig->getRoutableSrcSinkGroups(isInput);
+        if (srcSinkGroups.empty()) {
+            GTEST_SKIP() << "No routes to any attached " << direction(isInput, false) << " devices";
+        }
+        // First, set up a patch to ensure that its settings are accepted.
+        auto srcSinkGroup = *srcSinkGroups.begin();
+        auto srcSink = *srcSinkGroup.second.begin();
+        WithAudioPatch patch(srcSink.first, srcSink.second);
+        ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+        // Then use the same patch setting, except for having an invalid ID.
+        std::set<int32_t> patchIds;
+        ASSERT_NO_FATAL_FAILURE(GetAllPatchIds(&patchIds));
+        for (const auto patchId : GetNonExistentIds(patchIds)) {
+            AudioPatch patchWithNonExistendId = patch.get();
+            patchWithNonExistendId.id = patchId;
+            EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+                          module->setAudioPatch(patchWithNonExistendId, &patchWithNonExistendId))
+                    << "patch ID " << patchId;
+        }
+    }
+};
+
+// 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)); }
+
+TEST_PATCH_BOTH_DIRECTIONS(ResetPortConfigUsedByPatch);
+TEST_PATCH_BOTH_DIRECTIONS(SetInvalidPatch);
+TEST_PATCH_BOTH_DIRECTIONS(SetNonRoutablePatch);
+TEST_PATCH_BOTH_DIRECTIONS(SetPatch);
+TEST_PATCH_BOTH_DIRECTIONS(UpdateInvalidPatchId);
+TEST_PATCH_BOTH_DIRECTIONS(UpdatePatch);
+
+TEST_P(AudioModulePatch, ResetInvalidPatchId) {
+    std::set<int32_t> patchIds;
+    ASSERT_NO_FATAL_FAILURE(GetAllPatchIds(&patchIds));
+    for (const auto patchId : GetNonExistentIds(patchIds)) {
+        EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->resetAudioPatch(patchId))
+                << "patch ID " << patchId;
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(AudioCoreModuleTest, AudioCoreModule,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
+                         android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreModule);
+INSTANTIATE_TEST_SUITE_P(AudioStreamInTest, AudioStreamIn,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
+                         android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamIn);
+INSTANTIATE_TEST_SUITE_P(AudioStreamOutTest, AudioStreamOut,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
+                         android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamOut);
+INSTANTIATE_TEST_SUITE_P(AudioPatchTest, AudioModulePatch,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
+                         android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioModulePatch);
+
+class TestExecutionTracer : public ::testing::EmptyTestEventListener {
+  public:
+    void OnTestStart(const ::testing::TestInfo& test_info) override {
+        TraceTestState("Started", test_info);
+    }
+
+    void OnTestEnd(const ::testing::TestInfo& test_info) override {
+        TraceTestState("Completed", test_info);
+    }
+
+  private:
+    static void TraceTestState(const std::string& state, const ::testing::TestInfo& test_info) {
+        LOG(INFO) << state << " " << test_info.test_suite_name() << "::" << test_info.name();
+    }
+};
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
new file mode 100644
index 0000000..da8ca37
--- /dev/null
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -0,0 +1,235 @@
+/*
+ * 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 <memory>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "VtsHalAudioEffectFactory"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+
+#include "AudioHalBinderServiceUtil.h"
+#include "EffectFactoryHelper.h"
+#include "TestUtils.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectNullUuid;
+using aidl::android::hardware::audio::effect::EffectZeroUuid;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::Processing;
+using aidl::android::media::audio::common::AudioUuid;
+
+/// Effect factory testing.
+class EffectFactoryTest : public testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(mFactory.ConnectToFactoryService()); }
+
+    void TearDown() override { mFactory.DestroyEffects(); }
+
+    EffectFactoryHelper mFactory = EffectFactoryHelper(GetParam());
+
+    const Descriptor::Identity nullDesc = {.uuid = EffectNullUuid};
+    const Descriptor::Identity zeroDesc = {.uuid = EffectZeroUuid};
+};
+
+TEST_P(EffectFactoryTest, SetupAndTearDown) {
+    // Intentionally empty test body.
+}
+
+TEST_P(EffectFactoryTest, CanBeRestarted) {
+    ASSERT_NO_FATAL_FAILURE(mFactory.RestartFactoryService());
+}
+
+TEST_P(EffectFactoryTest, QueriedDescriptorList) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    EXPECT_NE(descriptors.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    // TODO: Factory eventually need to return the full list of MUST supported AOSP effects.
+    for (auto& desc : descriptors) {
+        EXPECT_NE(desc.type, EffectNullUuid);
+        EXPECT_NE(desc.uuid, EffectNullUuid);
+    }
+}
+
+TEST_P(EffectFactoryTest, QueriedDescriptorNotExistType) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(EffectNullUuid, std::nullopt, &descriptors);
+    EXPECT_EQ(descriptors.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, QueriedDescriptorNotExistInstance) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, EffectNullUuid, &descriptors);
+    EXPECT_EQ(descriptors.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, CreateAndDestroyOnce) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    auto numIds = mFactory.GetEffectIds().size();
+    EXPECT_NE(numIds, 0UL);
+
+    auto& effectMap = mFactory.GetEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    mFactory.DestroyEffects();
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    auto numIds = mFactory.GetEffectIds().size();
+    EXPECT_NE(numIds, 0UL);
+
+    auto& effectMap = mFactory.GetEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    mFactory.DestroyEffects();
+    EXPECT_EQ(effectMap.size(), 0UL);
+
+    // Create and destroy again
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    mFactory.DestroyEffects();
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    auto numIds = mFactory.GetEffectIds().size();
+    EXPECT_NE(numIds, 0UL);
+
+    auto& effectMap = mFactory.GetEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    // Create effect instances of same implementation
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), 2 * numIds);
+
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), 3 * numIds);
+
+    mFactory.DestroyEffects();
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+// Expect EX_ILLEGAL_ARGUMENT when create with invalid UUID.
+TEST_P(EffectFactoryTest, CreateWithInvalidUuid) {
+    std::vector<std::pair<Descriptor::Identity, binder_status_t>> descriptors;
+    descriptors.push_back(std::make_pair(nullDesc, EX_ILLEGAL_ARGUMENT));
+    descriptors.push_back(std::make_pair(zeroDesc, EX_ILLEGAL_ARGUMENT));
+
+    auto& effectMap = mFactory.GetEffectMap();
+    mFactory.CreateEffectsAndExpect(descriptors);
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+// Expect EX_ILLEGAL_ARGUMENT when destroy null interface.
+TEST_P(EffectFactoryTest, DestroyWithInvalidInterface) {
+    std::shared_ptr<IEffect> spDummyEffect(nullptr);
+
+    mFactory.DestroyEffectAndExpect(spDummyEffect, EX_ILLEGAL_ARGUMENT);
+}
+
+TEST_P(EffectFactoryTest, CreateAndRemoveReference) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    auto numIds = mFactory.GetEffectIds().size();
+    EXPECT_NE(numIds, 0UL);
+
+    auto& effectMap = mFactory.GetEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    // remove all reference
+    mFactory.ClearEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, CreateRemoveReferenceAndCreateDestroy) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    auto numIds = mFactory.GetEffectIds().size();
+    EXPECT_NE(numIds, 0UL);
+
+    auto& effectMap = mFactory.GetEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    // remove all reference
+    mFactory.ClearEffectMap();
+    EXPECT_EQ(effectMap.size(), 0UL);
+
+    // Create and destroy again
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    mFactory.DestroyEffects();
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, CreateRestartAndCreateDestroy) {
+    std::vector<Descriptor::Identity> descriptors;
+    mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
+    auto numIds = mFactory.GetEffectIds().size();
+    auto& effectMap = mFactory.GetEffectMap();
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    ASSERT_NO_FATAL_FAILURE(mFactory.RestartFactoryService());
+
+    mFactory.CreateEffects();
+    EXPECT_EQ(effectMap.size(), numIds);
+    mFactory.DestroyEffects();
+    EXPECT_EQ(effectMap.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, QueryProcess) {
+    std::vector<Processing> processing;
+    mFactory.QueryProcessing(std::nullopt, &processing);
+    // TODO: verify the number of process in example implementation after audio_effects.xml migrated
+}
+
+INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactoryTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EffectFactoryTest);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
new file mode 100644
index 0000000..7ed1f01
--- /dev/null
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -0,0 +1,358 @@
+/*
+ * 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 "VtsHalAudioEffectTargetTest"
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include <Utils.h>
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <aidl/android/media/audio/common/AudioDeviceType.h>
+
+#include "AudioHalBinderServiceUtil.h"
+#include "EffectHelper.h"
+#include "TestUtils.h"
+
+using namespace android;
+
+using ndk::ScopedAStatus;
+
+using aidl::android::hardware::audio::effect::CommandId;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::Parameter;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioDeviceType;
+
+class AudioEffectTest : public testing::TestWithParam<std::string>, public EffectHelper {
+  public:
+    AudioEffectTest() : EffectHelper(GetParam()) {}
+
+    void SetUp() override {
+        CreateEffects();
+        initParamCommonFormat();
+        initParamCommon();
+        // initParamSpecific();
+    }
+
+    void TearDown() override {
+        CloseEffects();
+        DestroyEffects();
+    }
+};
+
+TEST_P(AudioEffectTest, OpenEffectTest) {
+    OpenEffects();
+}
+
+TEST_P(AudioEffectTest, OpenAndCloseEffect) {
+    OpenEffects();
+    CloseEffects();
+}
+
+TEST_P(AudioEffectTest, CloseUnopenedEffectTest) {
+    CloseEffects();
+}
+
+TEST_P(AudioEffectTest, DoubleOpenCloseEffects) {
+    OpenEffects();
+    CloseEffects();
+    OpenEffects();
+    CloseEffects();
+
+    OpenEffects();
+    OpenEffects();
+    CloseEffects();
+
+    OpenEffects();
+    CloseEffects();
+    CloseEffects();
+}
+
+TEST_P(AudioEffectTest, GetDescriptors) {
+    GetEffectDescriptors();
+}
+
+TEST_P(AudioEffectTest, DescriptorIdExistAndUnique) {
+    auto checker = [&](const std::shared_ptr<IEffect>& effect) {
+        Descriptor desc;
+        std::vector<Descriptor::Identity> idList;
+        EXPECT_IS_OK(effect->getDescriptor(&desc));
+        QueryEffects(desc.common.id.type, desc.common.id.uuid, &idList);
+        EXPECT_EQ(idList.size(), 1UL);
+    };
+    ForEachEffect(checker);
+
+    // Check unique with a set
+    auto stringHash = [](const Descriptor::Identity& id) {
+        return std::hash<std::string>()(id.toString());
+    };
+    auto vec = GetCompleteEffectIdList();
+    std::unordered_set<Descriptor::Identity, decltype(stringHash)> idSet(0, stringHash);
+    for (auto it : vec) {
+        EXPECT_EQ(idSet.count(it), 0UL);
+        idSet.insert(it);
+    }
+}
+
+/// State testing.
+// An effect instance is in INIT state by default after it was created.
+TEST_P(AudioEffectTest, InitStateAfterCreation) {
+    ExpectState(State::INIT);
+}
+
+// An effect instance transfer to INIT state after it was open successfully with IEffect.open().
+TEST_P(AudioEffectTest, IdleStateAfterOpen) {
+    OpenEffects();
+    ExpectState(State::IDLE);
+    CloseEffects();
+}
+
+// An effect instance is in PROCESSING state after it receive an START command.
+TEST_P(AudioEffectTest, ProcessingStateAfterStart) {
+    OpenEffects();
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    CommandEffects(CommandId::STOP);
+    CloseEffects();
+}
+
+// An effect instance transfer to IDLE state after Command.Id.STOP in PROCESSING state.
+TEST_P(AudioEffectTest, IdleStateAfterStop) {
+    OpenEffects();
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    CommandEffects(CommandId::STOP);
+    ExpectState(State::IDLE);
+    CloseEffects();
+}
+
+// An effect instance transfer to IDLE state after Command.Id.RESET in PROCESSING state.
+TEST_P(AudioEffectTest, IdleStateAfterReset) {
+    OpenEffects();
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    CommandEffects(CommandId::RESET);
+    ExpectState(State::IDLE);
+    CloseEffects();
+}
+
+// An effect instance transfer to INIT if instance receive a close() call.
+TEST_P(AudioEffectTest, InitStateAfterClose) {
+    OpenEffects();
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    CommandEffects(CommandId::STOP);
+    ExpectState(State::IDLE);
+    CloseEffects();
+    ExpectState(State::INIT);
+}
+
+// An effect instance shouldn't accept any command before open.
+TEST_P(AudioEffectTest, NoCommandAcceptedBeforeOpen) {
+    ExpectState(State::INIT);
+    CommandEffectsExpectStatus(CommandId::START, EX_ILLEGAL_STATE);
+    CommandEffectsExpectStatus(CommandId::STOP, EX_ILLEGAL_STATE);
+    CommandEffectsExpectStatus(CommandId::RESET, EX_ILLEGAL_STATE);
+    ExpectState(State::INIT);
+}
+
+// No-op when receive STOP command in IDLE state.
+TEST_P(AudioEffectTest, StopCommandInIdleStateNoOp) {
+    ExpectState(State::INIT);
+    OpenEffects();
+    ExpectState(State::IDLE);
+    CommandEffects(CommandId::STOP);
+    ExpectState(State::IDLE);
+    CloseEffects();
+}
+
+// No-op when receive STOP command in IDLE state.
+TEST_P(AudioEffectTest, ResetCommandInIdleStateNoOp) {
+    ExpectState(State::INIT);
+    OpenEffects();
+    ExpectState(State::IDLE);
+    CommandEffects(CommandId::RESET);
+    ExpectState(State::IDLE);
+    CloseEffects();
+}
+
+// Repeat START and STOP command.
+TEST_P(AudioEffectTest, RepeatStartAndStop) {
+    OpenEffects();
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    CommandEffects(CommandId::STOP);
+    ExpectState(State::IDLE);
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    CommandEffects(CommandId::STOP);
+    ExpectState(State::IDLE);
+    CloseEffects();
+}
+
+// Repeat START and RESET command.
+TEST_P(AudioEffectTest, RepeatStartAndReset) {
+    OpenEffects();
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    CommandEffects(CommandId::RESET);
+    ExpectState(State::IDLE);
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    CommandEffects(CommandId::RESET);
+    ExpectState(State::IDLE);
+    CloseEffects();
+}
+
+// Repeat START and STOP command, try to close at PROCESSING state.
+TEST_P(AudioEffectTest, CloseProcessingStateEffects) {
+    OpenEffects();
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    CommandEffects(CommandId::STOP);
+    ExpectState(State::IDLE);
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    CloseEffects(EX_ILLEGAL_STATE);
+    // cleanup
+    CommandEffects(CommandId::STOP);
+    ExpectState(State::IDLE);
+}
+
+// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+TEST_P(AudioEffectTest, DestroyOpenEffects) {
+    // cleanup all effects.
+    CloseEffects();
+    DestroyEffects();
+
+    // open effects, destroy without close, expect to get EX_ILLEGAL_STATE status.
+    CreateEffects();
+    OpenEffects();
+    DestroyEffects(EX_ILLEGAL_STATE, 1);
+    CloseEffects();
+}
+
+/// Parameter testing.
+// Verify parameters pass in open can be successfully get.
+TEST_P(AudioEffectTest, VerifyParametersAfterOpen) {
+    OpenEffects();
+    VerifyParameters();
+    CloseEffects();
+}
+
+// Verify parameters pass in set can be successfully get.
+TEST_P(AudioEffectTest, SetAndGetParameter) {
+    OpenEffects();
+    VerifyParameters();
+    initParamCommon(1 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */,
+                    44100 /* oSampleRate */);
+    SetParameter();
+    VerifyParameters();
+    CloseEffects();
+}
+
+// Verify parameters pass in set can be successfully get.
+TEST_P(AudioEffectTest, SetAndGetParameterInProcessing) {
+    OpenEffects();
+    VerifyParameters();
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    initParamCommon(1 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */,
+                    44100 /* oSampleRate */);
+    SetParameter();
+    VerifyParameters();
+    CommandEffects(CommandId::STOP);
+    ExpectState(State::IDLE);
+    CloseEffects();
+}
+
+// Parameters kept after reset.
+TEST_P(AudioEffectTest, ResetAndVerifyParameter) {
+    OpenEffects();
+    VerifyParameters();
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    initParamCommon(1 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */,
+                    44100 /* oSampleRate */);
+    SetParameter();
+    VerifyParameters();
+    CommandEffects(CommandId::RESET);
+    ExpectState(State::IDLE);
+    VerifyParameters();
+    CloseEffects();
+}
+
+// Multiple instances of same implementation running.
+TEST_P(AudioEffectTest, MultipleInstancesRunning) {
+    CreateEffects(3);
+    ExpectState(State::INIT);
+    OpenEffects();
+    ExpectState(State::IDLE);
+    CommandEffects(CommandId::START);
+    ExpectState(State::PROCESSING);
+    initParamCommon(1 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */,
+                    44100 /* oSampleRate */);
+    SetParameter();
+    VerifyParameters();
+    CommandEffects(CommandId::STOP);
+    ExpectState(State::IDLE);
+    VerifyParameters();
+    CloseEffects();
+}
+
+// Send data to effects and expect it to consume by check statusMQ.
+TEST_P(AudioEffectTest, ExpectEffectsToConsumeDataInMQ) {
+    OpenEffects();
+    PrepareInputData(mWriteMQSize);
+
+    CommandEffects(CommandId::START);
+    writeToFmq(mWriteMQSize);
+    readFromFmq(mWriteMQSize);
+
+    ExpectState(State::PROCESSING);
+    CommandEffects(CommandId::STOP);
+    // cleanup
+    CommandEffects(CommandId::STOP);
+    ExpectState(State::IDLE);
+    CloseEffects();
+}
+
+INSTANTIATE_TEST_SUITE_P(AudioEffectTestTest, AudioEffectTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffectTest);
+
+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
new file mode 100644
index 0000000..3b9699b
--- /dev/null
+++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
@@ -0,0 +1,233 @@
+/*
+ * 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 <algorithm>
+#include <limits>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "VtsHalEqualizerTest"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+
+#include <Utils.h>
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <aidl/android/media/audio/common/AudioChannelLayout.h>
+#include <aidl/android/media/audio/common/AudioDeviceType.h>
+
+#include "AudioHalBinderServiceUtil.h"
+#include "EffectHelper.h"
+#include "TestUtils.h"
+#include "effect-impl/EffectUUID.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Capability;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectNullUuid;
+using aidl::android::hardware::audio::effect::Equalizer;
+using aidl::android::hardware::audio::effect::EqualizerTypeUUID;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::Parameter;
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEfectTargetTest.
+ */
+using EqualizerParamTestParam = std::tuple<int, int, int>;
+
+class EqualizerParamTest : public ::testing::TestWithParam<EqualizerParamTestParam>,
+                           public EffectHelper {
+  public:
+    EqualizerParamTest()
+        : EffectHelper(android::getAidlHalInstanceNames(IFactory::descriptor)[0]),
+          mParamPresetIndex(std::get<0 /* kPresetIndexRange */>(GetParam())),
+          mParamBandIndex(std::get<1 /* kBandIndexRange */>(GetParam())),
+          mParamBandLevel(std::get<2 /* kBandLevelRange */>(GetParam())) {}
+
+    void SetUp() override {
+        CreateEffectsWithUUID(EqualizerTypeUUID);
+        initParamCommonFormat();
+        initParamCommon();
+        initParamSpecific();
+        OpenEffects(EqualizerTypeUUID);
+        SCOPED_TRACE(testing::Message() << "preset: " << mParamPresetIndex << " bandIdx "
+                                        << mParamBandIndex << " level " << mParamBandLevel);
+    }
+
+    void TearDown() override {
+        CloseEffects();
+        DestroyEffects();
+        CleanUp();
+    }
+
+    const int mParamPresetIndex;
+    const int mParamBandIndex;
+    const int mParamBandLevel;
+
+    void SetAndGetEqualizerParameters() {
+        auto functor = [&](const std::shared_ptr<IEffect>& effect) {
+            for (auto& it : mTags) {
+                auto& tag = it.first;
+                auto& eq = it.second;
+
+                // validate parameter
+                Descriptor desc;
+                ASSERT_STATUS(EX_NONE, effect->getDescriptor(&desc));
+                const bool valid = isTagInRange(it.first, it.second, desc);
+                const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+                // set
+                Parameter expectParam;
+                Parameter::Specific specific;
+                specific.set<Parameter::Specific::equalizer>(*eq.get());
+                expectParam.set<Parameter::specific>(specific);
+                EXPECT_STATUS(expected, effect->setParameter(expectParam))
+                        << expectParam.toString();
+
+                // get
+                if (expected == EX_NONE) {
+                    Parameter getParam;
+                    Parameter::Specific::Id id;
+                    id.set<Parameter::Specific::Id::equalizerTag>(tag);
+                    // if set success, then get should match
+                    EXPECT_STATUS(expected, effect->getParameter(id, &getParam));
+                    EXPECT_EQ(expectParam, getParam) << "\n"
+                                                     << expectParam.toString() << "\n"
+                                                     << getParam.toString();
+                }
+            }
+        };
+        EXPECT_NO_FATAL_FAILURE(ForEachEffect(functor));
+    }
+
+    void addPresetParam(int preset) {
+        Equalizer eq;
+        eq.set<Equalizer::preset>(preset);
+        mTags.push_back({Equalizer::preset, std::make_unique<Equalizer>(std::move(eq))});
+    }
+
+    void addBandLevelsParam(std::vector<Equalizer::BandLevel>& bandLevels) {
+        Equalizer eq;
+        eq.set<Equalizer::bandLevels>(bandLevels);
+        mTags.push_back({Equalizer::bandLevels, std::make_unique<Equalizer>(std::move(eq))});
+    }
+
+    bool isTagInRange(const Equalizer::Tag& tag, const std::unique_ptr<Equalizer>& eq,
+                      const Descriptor& desc) const {
+        std::cout << "xxx" << toString(tag) << " " << desc.toString();
+        const Equalizer::Capability& eqCap = desc.capability.get<Capability::equalizer>();
+        switch (tag) {
+            case Equalizer::preset: {
+                int index = eq->get<Equalizer::preset>();
+                return isPresetIndexInRange(eqCap, index);
+            }
+            case Equalizer::bandLevels: {
+                auto& bandLevel = eq->get<Equalizer::bandLevels>();
+                return isBandIndexInRange(eqCap, bandLevel);
+            }
+            default:
+                return false;
+        }
+        return false;
+    }
+
+    bool isPresetIndexInRange(const Equalizer::Capability& cap, int idx) const {
+        const auto [min, max] =
+                std::minmax_element(cap.presets.begin(), cap.presets.end(),
+                                    [](const auto& a, const auto& b) { return a.index < b.index; });
+        return idx >= min->index && idx <= max->index;
+    }
+
+    bool isBandIndexInRange(const Equalizer::Capability& cap,
+                            const std::vector<Equalizer::BandLevel>& bandLevel) const {
+        for (auto& it : bandLevel) {
+            if (!isBandIndexInRange(cap, it.index)) return false;
+        }
+        return true;
+    }
+
+    bool isBandIndexInRange(const Equalizer::Capability& cap, int idx) const {
+        const auto [min, max] =
+                std::minmax_element(cap.bandFrequencies.begin(), cap.bandFrequencies.end(),
+                                    [](const auto& a, const auto& b) { return a.index < b.index; });
+        return idx >= min->index && idx <= max->index;
+    }
+
+  private:
+    Equalizer::VendorExtension mVendorExtension;
+    std::vector<std::pair<Equalizer::Tag, std::unique_ptr<Equalizer>>> mTags;
+
+    bool validCapabilityTag(Capability& cap) { return cap.getTag() == Capability::equalizer; }
+
+    void initParamSpecific() {
+        Equalizer eq;
+        eq.set<Equalizer::preset>(0);
+        Parameter::Specific specific;
+        specific.set<Parameter::Specific::equalizer>(eq);
+        setSpecific(specific);
+    }
+
+    void CleanUp() { mTags.clear(); }
+};
+
+TEST_P(EqualizerParamTest, SetAndGetPreset) {
+    EXPECT_NO_FATAL_FAILURE(addPresetParam(mParamPresetIndex));
+    SetAndGetEqualizerParameters();
+}
+
+TEST_P(EqualizerParamTest, SetAndGetSingleBand) {
+    Equalizer::BandLevel bandLevel = {mParamBandIndex, mParamBandLevel};
+    std::vector<Equalizer::BandLevel> bandLevels;
+    bandLevels.push_back(bandLevel);
+    EXPECT_NO_FATAL_FAILURE(addBandLevelsParam(bandLevels));
+    SetAndGetEqualizerParameters();
+}
+
+/**
+ Testing preset index range with [-10, 10], assuming the min/max preset index supported by
+effect is in this range.
+ This range is verified with IEffect.getDescriptor(): for any index supported vts expect EX_NONE
+from IEffect.setParameter(), otherwise expect EX_ILLEGAL_ARGUMENT.
+ */
+constexpr std::pair<int, int> kPresetIndexRange = {-1, 10};  // valid range [0, 9]
+constexpr std::pair<int, int> kBandIndexRange = {-1, 5};     // valid range [0, 4]
+constexpr std::pair<int, int> kBandLevelRange = {-5, 5};     // needs update with implementation
+
+INSTANTIATE_TEST_SUITE_P(
+        EqualizerTest, EqualizerParamTest,
+        ::testing::Combine(testing::Range(kPresetIndexRange.first, kPresetIndexRange.second),
+                           testing::Range(kBandIndexRange.first, kBandIndexRange.second),
+                           testing::Range(kBandLevelRange.first, kBandLevelRange.second)));
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EqualizerTest);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/audio/common/5.0/Android.bp b/audio/common/5.0/Android.bp
index fd8e85f..a6bb331 100644
--- a/audio/common/5.0/Android.bp
+++ b/audio/common/5.0/Android.bp
@@ -22,6 +22,6 @@
     gen_java_constants: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
     ],
 }
diff --git a/audio/common/all-versions/default/tests/hidlutils_tests.cpp b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
index e6e2280..93688fc 100644
--- a/audio/common/all-versions/default/tests/hidlutils_tests.cpp
+++ b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
@@ -1127,8 +1127,12 @@
     TypeParam emptyTags;
     EXPECT_EQ(emptyTags, HidlUtils::filterOutNonVendorTags(emptyTags));
 
-    TypeParam allVendorTags = {{"VX_GOOGLE_VR_42", "VX_GOOGLE_1E100"}};
-    EXPECT_EQ(allVendorTags, HidlUtils::filterOutNonVendorTags(allVendorTags));
+    // b/248421569, allocate two vendor tags at a time can run out of memory
+    // TypeParam allVendorTags = {{"VX_GOOGLE_VR_42", "VX_GOOGLE_1E100"}};
+    TypeParam allVendorTags1 = {{"VX_GOOGLE_VR_42"}};
+    EXPECT_EQ(allVendorTags1, HidlUtils::filterOutNonVendorTags(allVendorTags1));
+    TypeParam allVendorTags2 = {{"VX_GOOGLE_1E100"}};
+    EXPECT_EQ(allVendorTags2, HidlUtils::filterOutNonVendorTags(allVendorTags2));
 
     TypeParam oneVendorTag = {{"", "VX_GOOGLE_VR", "random_string"}};
     TypeParam oneVendorTagOnly = HidlUtils::filterOutNonVendorTags(oneVendorTag);
diff --git a/audio/common/all-versions/test/utility/src/ValidateXml.cpp b/audio/common/all-versions/test/utility/src/ValidateXml.cpp
index f111c01..4d6f003 100644
--- a/audio/common/all-versions/test/utility/src/ValidateXml.cpp
+++ b/audio/common/all-versions/test/utility/src/ValidateXml.cpp
@@ -63,11 +63,8 @@
         xmlSetGenericErrorFunc(this, errorCb);
     }
     ~Libxml2Global() {
-        // TODO: check if all those cleanup are needed
         xmlSetGenericErrorFunc(nullptr, nullptr);
-        xmlSchemaCleanupTypes();
         xmlCleanupParser();
-        xmlCleanupThreads();
     }
 
     const std::string& getErrors() { return errors; }
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index daed7a8..f51a8d0 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -49,7 +49,10 @@
 
 cc_test {
     name: "VtsHalAudioV2_0TargetTest",
-    defaults: ["VtsHalAudioTargetTest_defaults"],
+    defaults: [
+        "VtsHalAudioTargetTest_defaults",
+        "latest_android_media_audio_common_types_cpp_static",
+    ],
     tidy_timeout_srcs: [
         "2.0/AudioPrimaryHidlHalTest.cpp",
     ],
@@ -62,7 +65,6 @@
         "libmedia_helper",
         "android.hardware.audio@2.0",
         "android.hardware.audio.common@2.0",
-        "android.media.audio.common.types-V1-cpp",
     ],
     cflags: [
         "-DMAJOR_VERSION=2",
@@ -79,7 +81,10 @@
 
 cc_test {
     name: "VtsHalAudioV4_0TargetTest",
-    defaults: ["VtsHalAudioTargetTest_defaults"],
+    defaults: [
+        "VtsHalAudioTargetTest_defaults",
+        "latest_android_media_audio_common_types_cpp_static",
+    ],
     tidy_timeout_srcs: [
         "4.0/AudioPrimaryHidlHalTest.cpp",
     ],
@@ -92,7 +97,6 @@
         "libmedia_helper",
         "android.hardware.audio@4.0",
         "android.hardware.audio.common@4.0",
-        "android.media.audio.common.types-V1-cpp",
     ],
     cflags: [
         "-DMAJOR_VERSION=4",
@@ -109,7 +113,10 @@
 
 cc_test {
     name: "VtsHalAudioV5_0TargetTest",
-    defaults: ["VtsHalAudioTargetTest_defaults"],
+    defaults: [
+        "VtsHalAudioTargetTest_defaults",
+        "latest_android_media_audio_common_types_cpp_static",
+    ],
     srcs: [
         "5.0/AudioPrimaryHidlHalTest.cpp",
     ],
@@ -119,7 +126,6 @@
         "libmedia_helper",
         "android.hardware.audio@5.0",
         "android.hardware.audio.common@5.0",
-        "android.media.audio.common.types-V1-cpp",
     ],
     cflags: [
         "-DMAJOR_VERSION=5",
@@ -136,7 +142,10 @@
 
 cc_test {
     name: "VtsHalAudioV6_0TargetTest",
-    defaults: ["VtsHalAudioTargetTest_defaults"],
+    defaults: [
+        "VtsHalAudioTargetTest_defaults",
+        "latest_android_media_audio_common_types_cpp_static",
+    ],
     tidy_timeout_srcs: [
         "6.0/AudioPrimaryHidlHalTest.cpp",
     ],
@@ -150,7 +159,6 @@
         "libmedia_helper",
         "android.hardware.audio@6.0",
         "android.hardware.audio.common@6.0",
-        "android.media.audio.common.types-V1-cpp",
     ],
     cflags: [
         "-DMAJOR_VERSION=6",
@@ -244,7 +252,10 @@
 
 cc_test {
     name: "HalAudioV6_0GeneratorTest",
-    defaults: ["VtsHalAudioTargetTest_defaults"],
+    defaults: [
+        "VtsHalAudioTargetTest_defaults",
+        "latest_android_media_audio_common_types_cpp_static",
+    ],
     srcs: [
         "6.0/Generators.cpp",
         "tests/generators_tests.cpp",
@@ -252,7 +263,6 @@
     static_libs: [
         "android.hardware.audio@6.0",
         "android.hardware.audio.common@6.0",
-        "android.media.audio.common.types-V1-cpp",
         "libaudiofoundation",
         "libaudiopolicycomponents",
         "libmedia_helper",
diff --git a/audio/policy/1.0/xml/api/current.txt b/audio/policy/1.0/xml/api/current.txt
index 0b77d45..84a2b71 100644
--- a/audio/policy/1.0/xml/api/current.txt
+++ b/audio/policy/1.0/xml/api/current.txt
@@ -217,6 +217,10 @@
     enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_GAME;
     enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_MEDIA;
     enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION;
+    enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED;
+    enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT;
+    enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
+    enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_EVENT;
     enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
     enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_UNKNOWN;
     enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_VIRTUAL_SOURCE;
diff --git a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
index 3ce12e7..b58a6c8 100644
--- a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
+++ b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
@@ -347,6 +347,11 @@
             <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"/>
diff --git a/authsecret/aidl/Android.bp b/authsecret/aidl/Android.bp
index 432c1b9..90e128d 100644
--- a/authsecret/aidl/Android.bp
+++ b/authsecret/aidl/Android.bp
@@ -16,11 +16,6 @@
         java: {
             platform_apis: true,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions: ["1"],
 }
diff --git a/automotive/OWNERS b/automotive/OWNERS
index 43c5f3e..09e257c 100644
--- a/automotive/OWNERS
+++ b/automotive/OWNERS
@@ -1,6 +1 @@
-pirozzoj@google.com
-twasilczyk@google.com
-krachuri@google.com
-gurunagarajan@google.com
-keunyoung@google.com
-felipeal@google.com
+include platform/packages/services/Car:/OWNERS
diff --git a/automotive/audiocontrol/OWNERS b/automotive/audiocontrol/OWNERS
new file mode 100644
index 0000000..f55eff3
--- /dev/null
+++ b/automotive/audiocontrol/OWNERS
@@ -0,0 +1 @@
+oscarazu@google.com
diff --git a/automotive/audiocontrol/aidl/Android.bp b/automotive/audiocontrol/aidl/Android.bp
index e5f7a4f..03dab08 100644
--- a/automotive/audiocontrol/aidl/Android.bp
+++ b/automotive/audiocontrol/aidl/Android.bp
@@ -15,7 +15,7 @@
     srcs: ["android/hardware/automotive/audiocontrol/*.aidl"],
     imports: [
         "android.hardware.audio.common-V1",
-        "android.media.audio.common.types-V1",
+        "android.media.audio.common.types-V2",
     ],
     stability: "vintf",
     backend: {
@@ -33,14 +33,14 @@
             version: "1",
             imports: [
                 "android.hardware.audio.common-V1",
-                "android.media.audio.common.types-V1",
+                "android.media.audio.common.types-V2",
             ],
         },
         {
             version: "2",
             imports: [
                 "android.hardware.audio.common-V1",
-                "android.media.audio.common.types-V1",
+                "android.media.audio.common.types-V2",
             ],
         },
 
diff --git a/automotive/audiocontrol/aidl/vts/Android.bp b/automotive/audiocontrol/aidl/vts/Android.bp
index 3d4be48..edac160 100644
--- a/automotive/audiocontrol/aidl/vts/Android.bp
+++ b/automotive/audiocontrol/aidl/vts/Android.bp
@@ -24,6 +24,8 @@
 cc_test {
     name: "VtsAidlHalAudioControlTest",
     defaults: [
+        "latest_android_media_audio_common_types_cpp_static",
+        "latest_android_hardware_audio_common_cpp_static",
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
@@ -38,8 +40,6 @@
     ],
     static_libs: [
         "android.hardware.automotive.audiocontrol-V2-cpp",
-        "android.hardware.audio.common-V1-cpp",
-        "android.media.audio.common.types-V1-cpp",
         "libgmock",
     ],
     test_suites: [
diff --git a/automotive/can/OWNERS b/automotive/can/OWNERS
new file mode 100644
index 0000000..ffa4828
--- /dev/null
+++ b/automotive/can/OWNERS
@@ -0,0 +1,3 @@
+kevinme@google.com
+chrisweir@google.com
+twasilczyk@google.com
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 623438f..18a3329 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -250,8 +250,7 @@
             // Stream configurations are found in metadata
             RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
             for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
-                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
-                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
                     targetCfg.width = ptr->width;
                     targetCfg.height = ptr->height;
                     targetCfg.format = static_cast<PixelFormat>(ptr->format);
@@ -2017,13 +2016,12 @@
             // Stream configurations are found in metadata
             RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
             for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
-                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
-                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
-
+                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
                     if (ptr->width * ptr->height > maxArea &&
                         ptr->framerate >= minReqFps) {
                         targetCfg.width = ptr->width;
                         targetCfg.height = ptr->height;
+                        targetCfg.format = static_cast<PixelFormat>(ptr->format);
 
                         maxArea = ptr->width * ptr->height;
                         foundCfg = true;
@@ -2032,8 +2030,6 @@
                 ++ptr;
             }
         }
-        targetCfg.format =
-            static_cast<PixelFormat>(HAL_PIXEL_FORMAT_RGBA_8888);
 
         if (!foundCfg) {
             // Current EVS camera does not provide stream configurations in the
@@ -2120,13 +2116,12 @@
             // Stream configurations are found in metadata
             RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
             for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
-                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
-                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
-
+                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
                     if (ptr->width * ptr->height > maxArea &&
                         ptr->framerate >= minReqFps) {
                         targetCfg.width = ptr->width;
                         targetCfg.height = ptr->height;
+                        targetCfg.format = static_cast<PixelFormat>(ptr->format);
 
                         maxArea = ptr->width * ptr->height;
                         foundCfg = true;
@@ -2135,8 +2130,6 @@
                 ++ptr;
             }
         }
-        targetCfg.format =
-            static_cast<PixelFormat>(HAL_PIXEL_FORMAT_RGBA_8888);
 
         if (!foundCfg) {
             LOG(INFO) << "Device " << cam.v1.cameraId
diff --git a/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp b/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
index 9c6c573..3ea1eaa 100644
--- a/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
+++ b/automotive/evs/aidl/vts/VtsHalEvsTargetTest.cpp
@@ -231,8 +231,7 @@
             // Stream configurations are found in metadata
             RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
             for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
-                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
-                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
                     targetCfg.width = ptr->width;
                     targetCfg.height = ptr->height;
                     targetCfg.format = static_cast<PixelFormat>(ptr->format);
@@ -1732,11 +1731,11 @@
             // Stream configurations are found in metadata
             RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
             for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
-                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
-                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
                     if (ptr->width * ptr->height > maxArea && ptr->framerate >= minReqFps) {
                         targetCfg.width = ptr->width;
                         targetCfg.height = ptr->height;
+                        targetCfg.format = static_cast<PixelFormat>(ptr->format);
 
                         maxArea = ptr->width * ptr->height;
                         foundCfg = true;
@@ -1745,7 +1744,6 @@
                 ++ptr;
             }
         }
-        targetCfg.format = static_cast<PixelFormat>(HAL_PIXEL_FORMAT_RGBA_8888);
 
         if (!foundCfg) {
             // Current EVS camera does not provide stream configurations in the
@@ -1829,11 +1827,11 @@
             // Stream configurations are found in metadata
             RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
             for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
-                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
-                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
                     if (ptr->width * ptr->height > maxArea && ptr->framerate >= minReqFps) {
                         targetCfg.width = ptr->width;
                         targetCfg.height = ptr->height;
+                        targetCfg.format = static_cast<PixelFormat>(ptr->format);
 
                         maxArea = ptr->width * ptr->height;
                         foundCfg = true;
@@ -1842,7 +1840,6 @@
                 ++ptr;
             }
         }
-        targetCfg.format = static_cast<PixelFormat>(HAL_PIXEL_FORMAT_RGBA_8888);
 
         if (!foundCfg) {
             LOG(INFO) << "Device " << cam.id
diff --git a/automotive/occupant_awareness/aidl/Android.bp b/automotive/occupant_awareness/aidl/Android.bp
index 6ddc127..1a8124c 100644
--- a/automotive/occupant_awareness/aidl/Android.bp
+++ b/automotive/occupant_awareness/aidl/Android.bp
@@ -23,11 +23,6 @@
                 "com.android.car.framework",
             ],
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions: ["1"],
 }
diff --git a/automotive/sv/OWNERS b/automotive/sv/OWNERS
new file mode 100644
index 0000000..af6788b
--- /dev/null
+++ b/automotive/sv/OWNERS
@@ -0,0 +1 @@
+tanmayp@google.com
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index 12e15f9..2968232 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -33,7 +33,7 @@
     auto store = std::make_unique<VehiclePropertyStore>();
     auto connector = std::make_unique<DefaultVehicleConnector>();
     auto hal = std::make_unique<DefaultVehicleHal>(store.get(), connector.get());
-    auto service = std::make_unique<VehicleHalManager>(hal.get());
+    auto service = android::sp<VehicleHalManager>::make(hal.get());
     connector->setValuePool(hal->getValuePool());
 
     android::hardware::configureRpcThreadpool(4, true /* callerWillJoin */);
diff --git a/bluetooth/1.0/Android.bp b/bluetooth/1.0/Android.bp
index 20775dd..bd1ca69 100644
--- a/bluetooth/1.0/Android.bp
+++ b/bluetooth/1.0/Android.bp
@@ -23,6 +23,6 @@
     gen_java: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
     ],
 }
diff --git a/bluetooth/1.0/default/test/fuzzer/bluetoothV1.0_fuzzer.cpp b/bluetooth/1.0/default/test/fuzzer/bluetoothV1.0_fuzzer.cpp
index 90cdc66..fb8df99 100644
--- a/bluetooth/1.0/default/test/fuzzer/bluetoothV1.0_fuzzer.cpp
+++ b/bluetooth/1.0/default/test/fuzzer/bluetoothV1.0_fuzzer.cpp
@@ -88,11 +88,18 @@
     }
     mBtHci->close();
     mBtHci.clear();
+    for (size_t i = 0; i < mFdCount; ++i) {
+      if (mFdList[i]) {
+        close(mFdList[i]);
+      }
+    }
   }
   bool init(const uint8_t* data, size_t size);
   void process();
 
  private:
+  size_t mFdCount = 1;
+  int32_t mFdList[CH_MAX] = {0};
   sp<BluetoothHci> mBtHci = nullptr;
   FuzzedDataProvider* mFdp = nullptr;
 };
@@ -143,17 +150,15 @@
   bool shouldSetH4Protocol = mFdp->ConsumeBool();
   BtVendor* btVendor = BtVendor::getInstance();
 
-  size_t fdcount = 1;
-  int32_t fdList[CH_MAX] = {0};
   if (!shouldSetH4Protocol) {
-    fdcount = mFdp->ConsumeIntegralInRange<size_t>(kMinFdcount, CH_MAX - 1);
+    mFdCount = mFdp->ConsumeIntegralInRange<size_t>(kMinFdcount, CH_MAX - 1);
   }
 
-  for (size_t i = 0; i < fdcount; ++i) {
-    fdList[i] = open("/dev/null", O_RDWR | O_CREAT);
+  for (size_t i = 0; i < mFdCount; ++i) {
+    mFdList[i] = open("/dev/null", O_RDWR | O_CREAT);
   }
 
-  btVendor->populateFdList(fdList, fdcount);
+  btVendor->populateFdList(mFdList, mFdCount);
   mBtHci->initialize(bluetoothCallback);
 
   if (!bluetoothCallback->isInitialized) {
@@ -181,12 +186,6 @@
   }
 
   btVendor->callRemainingCbacks();
-
-  for (size_t i = 0; i < fdcount; ++i) {
-    if (fdList[i]) {
-      close(fdList[i]);
-    }
-  }
 }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
diff --git a/bluetooth/1.1/Android.bp b/bluetooth/1.1/Android.bp
index 4ac2009..f8a05f1 100644
--- a/bluetooth/1.1/Android.bp
+++ b/bluetooth/1.1/Android.bp
@@ -23,6 +23,6 @@
     gen_java: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
     ],
 }
diff --git a/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.xml b/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.xml
index d64751a..98b62ef 100644
--- a/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.xml
+++ b/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.xml
@@ -20,8 +20,11 @@
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
     </target_preparer>
 
-    <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
-        <option name="bluetooth" value="off" />
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="settings put global ble_scan_always_enabled 0" />
+        <option name="run-command" value="su u$(am get-current-user)_system svc bluetooth disable" />
+        <option name="teardown-command" value="su u$(am get-current-user)_system svc bluetooth enable" />
+        <option name="teardown-command" value="settings put global ble_scan_always_enabled 1" />
     </target_preparer>
 
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
diff --git a/bluetooth/a2dp/1.0/Android.bp b/bluetooth/a2dp/1.0/Android.bp
index 20776dc..6ffbefa 100644
--- a/bluetooth/a2dp/1.0/Android.bp
+++ b/bluetooth/a2dp/1.0/Android.bp
@@ -23,6 +23,6 @@
     gen_java: false,
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
     ],
 }
diff --git a/bluetooth/audio/2.0/Android.bp b/bluetooth/audio/2.0/Android.bp
index e4d48c1..725ec11 100644
--- a/bluetooth/audio/2.0/Android.bp
+++ b/bluetooth/audio/2.0/Android.bp
@@ -26,6 +26,6 @@
     gen_java: false,
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
     ],
 }
diff --git a/bluetooth/audio/2.1/Android.bp b/bluetooth/audio/2.1/Android.bp
index 1175fb3..4ca0bef 100644
--- a/bluetooth/audio/2.1/Android.bp
+++ b/bluetooth/audio/2.1/Android.bp
@@ -25,7 +25,7 @@
     ],
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
     ],
     gen_java: false,
 }
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
index c581702..4aea83f 100644
--- a/bluetooth/audio/aidl/Android.bp
+++ b/bluetooth/audio/aidl/Android.bp
@@ -40,12 +40,9 @@
             enabled: false,
         },
         ndk: {
-            vndk: {
-                enabled: true,
-            },
             apex_available: [
                 "//apex_available:platform",
-                "com.android.bluetooth",
+                "com.android.btservices",
             ],
             min_sdk_version: "31",
         },
diff --git a/boot/1.1/default/boot_control/Android.bp b/boot/1.1/default/boot_control/Android.bp
index ad71700..6aa30c2 100644
--- a/boot/1.1/default/boot_control/Android.bp
+++ b/boot/1.1/default/boot_control/Android.bp
@@ -25,8 +25,6 @@
 
 cc_defaults {
     name: "libboot_control_defaults",
-    vendor: true,
-    recovery_available: true,
     relative_install_path: "hw",
 
     cflags: [
@@ -42,7 +40,7 @@
         "liblog",
     ],
     static_libs: [
-        "libbootloader_message_vendor",
+        "libbootloader_message",
         "libfstab",
     ],
 }
@@ -51,6 +49,8 @@
     name: "libboot_control",
     defaults: ["libboot_control_defaults"],
     export_include_dirs: ["include"],
+    recovery_available: true,
+    vendor_available: true,
 
     srcs: ["libboot_control.cpp"],
 }
@@ -58,6 +58,8 @@
 cc_library_shared {
     name: "bootctrl.default",
     defaults: ["libboot_control_defaults"],
+    recovery_available: true,
+    vendor_available: true,
 
     srcs: ["legacy_boot_control.cpp"],
 
diff --git a/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h b/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
index ac17d6d..572a8b6 100644
--- a/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
+++ b/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
@@ -25,9 +25,8 @@
 
 // Helper library to implement the IBootControl HAL using the misc partition.
 class BootControl {
-  using MergeStatus = ::android::hardware::boot::V1_1::MergeStatus;
-
  public:
+  using MergeStatus = ::android::hardware::boot::V1_1::MergeStatus;
   bool Init();
   unsigned int GetNumberSlots();
   unsigned int GetCurrentSlot();
diff --git a/boot/1.1/default/boot_control/include/private/boot_control_definition.h b/boot/1.1/default/boot_control/include/private/boot_control_definition.h
index 8f02111..57c2f73 100644
--- a/boot/1.1/default/boot_control/include/private/boot_control_definition.h
+++ b/boot/1.1/default/boot_control/include/private/boot_control_definition.h
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#include <stdint.h>
+
+#include <bootloader_message/bootloader_message.h>
 
 /**
  * The A/B-specific bootloader message structure (4-KiB).
diff --git a/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp b/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
index c38f257..05f136e 100644
--- a/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
+++ b/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
@@ -1,4 +1,5 @@
 /*
+
  * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,6 +20,7 @@
 #include <vector>
 
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <android/hardware/boot/1.1/IBootControl.h>
 #include <android/hardware/boot/1.1/types.h>
 #include <gmock/gmock.h>
@@ -37,9 +39,21 @@
 using ::android::hardware::boot::V1_1::MergeStatus;
 using ::testing::Contains;
 
+bool IsVirtualAbEnabled();
+
+#define SKIP_IF_NON_VIRTUAL_AB()                                                        \
+    do {                                                                                \
+        if (!IsVirtualAbEnabled()) GTEST_SKIP() << "Test for Virtual A/B devices only"; \
+    } while (0)
+
+bool IsVirtualAbEnabled() {
+    return android::base::GetBoolProperty("ro.virtual_ab.enabled", false);
+}
+
 class BootHidlTest : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
+        SKIP_IF_NON_VIRTUAL_AB();
         boot = IBootControl::getService(GetParam());
         ASSERT_NE(boot, nullptr);
 
diff --git a/boot/aidl/Android.bp b/boot/aidl/Android.bp
new file mode 100644
index 0000000..be38245
--- /dev/null
+++ b/boot/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.boot",
+    vendor_available: true,
+    srcs: ["android/hardware/boot/*.aidl"],
+    stability: "vintf",
+    recovery_available: true,
+    backend: {
+        java: {
+            sdk_version: "module_current",
+        },
+        cpp: {
+            enabled: false,
+        },
+    },
+}
diff --git a/boot/aidl/aidl_api/android.hardware.boot/current/android/hardware/boot/IBootControl.aidl b/boot/aidl/aidl_api/android.hardware.boot/current/android/hardware/boot/IBootControl.aidl
new file mode 100644
index 0000000..c8ab51e
--- /dev/null
+++ b/boot/aidl/aidl_api/android.hardware.boot/current/android/hardware/boot/IBootControl.aidl
@@ -0,0 +1,50 @@
+//
+// 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.boot;
+@VintfStability
+interface IBootControl {
+  int getActiveBootSlot();
+  int getCurrentSlot();
+  int getNumberSlots();
+  android.hardware.boot.MergeStatus getSnapshotMergeStatus();
+  String getSuffix(in int slot);
+  boolean isSlotBootable(in int slot);
+  boolean isSlotMarkedSuccessful(in int slot);
+  void markBootSuccessful();
+  void setActiveBootSlot(in int slot);
+  void setSlotAsUnbootable(in int slot);
+  void setSnapshotMergeStatus(in android.hardware.boot.MergeStatus status);
+  const int INVALID_SLOT = -1;
+  const int COMMAND_FAILED = -2;
+}
diff --git a/boot/aidl/aidl_api/android.hardware.boot/current/android/hardware/boot/MergeStatus.aidl b/boot/aidl/aidl_api/android.hardware.boot/current/android/hardware/boot/MergeStatus.aidl
new file mode 100644
index 0000000..53c6204
--- /dev/null
+++ b/boot/aidl/aidl_api/android.hardware.boot/current/android/hardware/boot/MergeStatus.aidl
@@ -0,0 +1,42 @@
+//
+// 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.boot;
+@Backing(type="int") @VintfStability
+enum MergeStatus {
+  NONE = 0,
+  UNKNOWN = 1,
+  SNAPSHOTTED = 2,
+  MERGING = 3,
+  CANCELLED = 4,
+}
diff --git a/boot/aidl/android/hardware/boot/IBootControl.aidl b/boot/aidl/android/hardware/boot/IBootControl.aidl
new file mode 100644
index 0000000..6c9e8ce
--- /dev/null
+++ b/boot/aidl/android/hardware/boot/IBootControl.aidl
@@ -0,0 +1,158 @@
+//
+// 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.boot;
+
+import android.hardware.boot.MergeStatus;
+
+@VintfStability
+interface IBootControl {
+    const int INVALID_SLOT = -1;
+    const int COMMAND_FAILED = -2;
+    /**
+     * Returns the active slot to boot into on the next boot. If
+     * setActiveBootSlot() has been called, the getter function should return the
+     * same slot as the one provided in the last setActiveBootSlot() call.
+     * The returned value is always guaranteed to be strictly less than the
+     * value returned by getNumberSlots. Slots start at 0 and finish at
+     * getNumberSlots() - 1. For instance, a system with A/B must return 0 or 1.
+     * @return the active slot to boot into on the next boot.
+     */
+    int getActiveBootSlot();
+
+    /**
+     * getCurrentSlot() returns the slot number of that the current boot is booted
+     * from, for example slot number 0 (Slot A). It is assumed that if the current
+     * slot is A, then the block devices underlying B can be accessed directly
+     * without any risk of corruption.
+     * The returned value is always guaranteed to be strictly less than the
+     * value returned by getNumberSlots. Slots start at 0 and finish at
+     * getNumberSlots() - 1. The value returned here must match the suffix passed
+     * from the bootloader, regardless of which slot is active or successful.
+     * @return the slot number of that the current boot is booted
+     */
+    int getCurrentSlot();
+
+    /**
+     * getNumberSlots() returns the number of available slots.
+     * For instance, a system with a single set of partitions must return
+     * 1, a system with A/B must return 2, A/B/C -> 3 and so on. A system with
+     * less than two slots doesn't support background updates, for example if
+     * running from a virtual machine with only one copy of each partition for the
+     * purpose of testing.
+     * @return number of available slots
+     */
+    int getNumberSlots();
+
+    /**
+     * Returns whether a snapshot-merge of any dynamic partition is in progress.
+     *
+     * This function must return the merge status set by the last setSnapshotMergeStatus call and
+     * recorded by the bootloader with one exception. If the partitions are being flashed from the
+     * bootloader such that the pending merge must be canceled (for example, if the super partition
+     * is being flashed), this function must return CANCELLED.
+     *
+     * @param out success True if the merge status is read successfully, false otherwise.
+     * @return Merge status.
+     */
+    MergeStatus getSnapshotMergeStatus();
+
+    /**
+     * getSuffix() returns the string suffix used by partitions that correspond to
+     * the slot number passed in as a parameter. The bootloader must pass the
+     * suffix of the currently active slot either through a kernel command line
+     * property at androidboot.slot_suffix, or the device tree at
+     * /firmware/android/slot_suffix.
+     * @return suffix for the input slot, or the empty string "" if slot
+     * does not match an existing slot.
+     */
+    String getSuffix(in int slot);
+
+    /**
+     * isSlotBootable() returns if the slot passed in parameter is bootable. Note
+     * that slots can be made unbootable by both the bootloader and by the OS
+     * using setSlotAsUnbootable.
+     * @return true if the slot is bootable, false if it's not.
+     * @throws service specific error INVALID_SLOT if slot is invalid.
+     */
+    boolean isSlotBootable(in int slot);
+
+    /**
+     * isSlotMarkedSuccessful() returns if the slot passed in parameter has been
+     * marked as successful using markBootSuccessful. Note that only the current
+     * slot can be marked as successful but any slot can be queried.
+     * @return true if the slot has been marked as successful, false if it has
+     * not.
+     * @throws service specific error INVALID_SLOT if slot is invalid.
+     */
+    boolean isSlotMarkedSuccessful(in int slot);
+
+    /**
+     * markBootSuccessful() marks the current slot as having booted successfully.
+     *
+     * @throws Service specific error COMMAND_FAILED if command failed.
+     */
+    void markBootSuccessful();
+
+    /**
+     * setActiveBootSlot() marks the slot passed in parameter as the active boot
+     * slot (see getCurrentSlot for an explanation of the "slot" parameter). This
+     * overrides any previous call to setSlotAsUnbootable.
+     * @throws Service specific error INVALID_SLOT if slot is invalid, or COMMAND_FAILED if
+     * operation failed.
+     */
+    void setActiveBootSlot(in int slot);
+
+    /**
+     * setSlotAsUnbootable() marks the slot passed in parameter as
+     * an unbootable. This can be used while updating the contents of the slot's
+     * partitions, so that the system must not attempt to boot a known bad set up.
+     * @throws Service specific error INVALID_SLOT if slot is invalid, or COMMAND_FAILED if
+     * operation failed.
+     */
+    void setSlotAsUnbootable(in int slot);
+
+    /**
+     * Sets whether a snapshot-merge of any dynamic partition is in progress.
+     *
+     * After the merge status is set to a given value, subsequent calls to
+     * getSnapshotMergeStatus must return the set value.
+     *
+     * The merge status must be persistent across reboots. That is, getSnapshotMergeStatus
+     * must return the same value after a reboot if the merge status is not altered in any way
+     * (e.g. set by setSnapshotMergeStatus or set to CANCELLED by bootloader).
+     *
+     * Read/write access to the merge status must be atomic. When the HAL is processing a
+     * setSnapshotMergeStatus call, all subsequent calls to getSnapshotMergeStatus must block until
+     * setSnapshotMergeStatus has returned.
+     *
+     * A MERGING state indicates that dynamic partitions are partially comprised by blocks in the
+     * userdata partition.
+     *
+     * When the merge status is set to MERGING, the following operations must be prohibited from the
+     * bootloader:
+     *  - Flashing or erasing "userdata" or "metadata".
+     *
+     * The following operations may be prohibited when the status is set to MERGING. If not
+     * prohibited, it is recommended that the user receive a warning.
+     *  - Changing the active slot (e.g. via "fastboot set_active")
+     *
+     * @param status Merge status.
+     *
+     * @throws service specific error COMMAND_FAILED if operation failed.
+     */
+    void setSnapshotMergeStatus(in MergeStatus status);
+}
diff --git a/boot/aidl/android/hardware/boot/MergeStatus.aidl b/boot/aidl/android/hardware/boot/MergeStatus.aidl
new file mode 100644
index 0000000..16ac85f
--- /dev/null
+++ b/boot/aidl/android/hardware/boot/MergeStatus.aidl
@@ -0,0 +1,42 @@
+//
+// 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.boot;
+
+@VintfStability
+@Backing(type="int")
+enum MergeStatus {
+    /**
+     * No snapshot or merge is in progress.
+     */
+    NONE = 0,
+    /**
+     * The merge status could not be determined.
+     */
+    UNKNOWN,
+    /**
+     * Partitions are being snapshotted, but no merge has been started.
+     */
+    SNAPSHOTTED,
+    /**
+     * At least one partition has merge is in progress.
+     */
+    MERGING,
+    /**
+     * A merge was in progress, but it was canceled by the bootloader.
+     */
+    CANCELLED,
+}
diff --git a/boot/aidl/client/Android.bp b/boot/aidl/client/Android.bp
new file mode 100644
index 0000000..db4a7ea
--- /dev/null
+++ b/boot/aidl/client/Android.bp
@@ -0,0 +1,31 @@
+
+
+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 {
+    name: "libboot_control_client",
+    srcs: [
+        "BootControlClient.cpp"
+    ],
+    export_include_dirs: ["include"],
+    export_shared_lib_headers: ["android.hardware.boot-V1-ndk"],
+    recovery_available: true,
+    shared_libs: [
+        "android.hardware.boot-V1-ndk",
+        "android.hardware.boot@1.0",
+        "android.hardware.boot@1.1",
+        "android.hardware.boot@1.2",
+        "libhidlbase",
+        "libbinder_ndk",
+        "libbase",
+        "libcutils",
+        "libutils",
+    ],
+}
diff --git a/boot/aidl/client/BootControlClient.cpp b/boot/aidl/client/BootControlClient.cpp
new file mode 100644
index 0000000..89258d2
--- /dev/null
+++ b/boot/aidl/client/BootControlClient.cpp
@@ -0,0 +1,364 @@
+/*
+ * 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 <BootControlClient.h>
+
+#include <aidl/android/hardware/boot/IBootControl.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/hardware/boot/1.0/IBootControl.h>
+#include <android/hardware/boot/1.1/IBootControl.h>
+#include <android/hardware/boot/1.2/IBootControl.h>
+#include "utils/StrongPointer.h"
+
+#define CONCAT(x, y) x##y
+
+#define LOG_NDK_STATUS(x)                                                                   \
+    do {                                                                                    \
+        const auto CONCAT(status, __COUNTER__) = x;                                         \
+        if (!CONCAT(status, __COUNTER__).isOk()) {                                          \
+            LOG(ERROR) << #x << " failed " << CONCAT(status, __COUNTER__).getDescription(); \
+        }                                                                                   \
+    } while (0)
+
+using aidl::android::hardware::boot::MergeStatus;
+
+std::ostream& operator<<(std::ostream& os, MergeStatus status) {
+    switch (status) {
+        case MergeStatus::NONE:
+            os << "MergeStatus::NONE";
+            break;
+        case MergeStatus::UNKNOWN:
+            os << "MergeStatus::UNKNOWN";
+            break;
+        case MergeStatus::SNAPSHOTTED:
+            os << "MergeStatus::SNAPSHOTTED";
+            break;
+        case MergeStatus::MERGING:
+            os << "MergeStatus::MERGING";
+            break;
+        case MergeStatus::CANCELLED:
+            os << "MergeStatus::CANCELLED";
+            break;
+        default:
+            os << static_cast<int>(status);
+            break;
+    }
+    return os;
+}
+
+namespace android::hal {
+class BootControlClientAidl final : public BootControlClient {
+    using IBootControl = ::aidl::android::hardware::boot::IBootControl;
+
+  public:
+    BootControlClientAidl(std::shared_ptr<IBootControl> module) : module_(module) {}
+
+    BootControlVersion GetVersion() const override { return BootControlVersion::BOOTCTL_AIDL; }
+
+    ~BootControlClientAidl() = default;
+    virtual int32_t GetNumSlots() const {
+        int32_t ret = -1;
+        LOG_NDK_STATUS(module_->getNumberSlots(&ret));
+        return ret;
+    }
+
+    int32_t GetCurrentSlot() const {
+        int32_t ret = -1;
+        LOG_NDK_STATUS(module_->getCurrentSlot(&ret));
+        return ret;
+    }
+    MergeStatus getSnapshotMergeStatus() const {
+        MergeStatus status = MergeStatus::UNKNOWN;
+        LOG_NDK_STATUS(module_->getSnapshotMergeStatus(&status));
+        return status;
+    }
+    std::string GetSuffix(int32_t slot) const {
+        std::string ret;
+        const auto status = module_->getSuffix(slot, &ret);
+        if (!status.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
+                       << " failed " << status.getDescription();
+            return {};
+        }
+        return ret;
+    }
+
+    std::optional<bool> IsSlotBootable(int32_t slot) const {
+        bool ret = false;
+        const auto status = module_->isSlotBootable(slot, &ret);
+        if (!status.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
+                       << " failed " << status.getDescription();
+            return {};
+        }
+        return ret;
+    }
+
+    CommandResult MarkSlotUnbootable(int32_t slot) {
+        const auto status = module_->setSlotAsUnbootable(slot);
+        if (!status.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
+                       << " failed " << status.getDescription();
+        }
+        return {.success = status.isOk(), .errMsg = status.getDescription()};
+    }
+
+    CommandResult SetActiveBootSlot(int slot) {
+        const auto status = module_->setActiveBootSlot(slot);
+        if (!status.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
+                       << " failed " << status.getDescription();
+        }
+        return {.success = status.isOk(), .errMsg = status.getDescription()};
+    }
+    int GetActiveBootSlot() const {
+        int ret = -1;
+        LOG_NDK_STATUS(module_->getActiveBootSlot(&ret));
+        return ret;
+    }
+
+    // Check if |slot| is marked boot successfully.
+    std::optional<bool> IsSlotMarkedSuccessful(int slot) const {
+        bool ret = false;
+        const auto status = module_->isSlotMarkedSuccessful(slot, &ret);
+        if (!status.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
+                       << " failed " << status.getDescription();
+            return {};
+        }
+        return ret;
+    }
+
+    CommandResult MarkBootSuccessful() {
+        const auto status = module_->markBootSuccessful();
+        if (!status.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << " failed " << status.getDescription();
+        }
+        return {.success = status.isOk(), .errMsg = status.getDescription()};
+    }
+
+    CommandResult SetSnapshotMergeStatus(aidl::android::hardware::boot::MergeStatus merge_status) {
+        const auto status = module_->setSnapshotMergeStatus(merge_status);
+        if (!status.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")"
+                       << " failed " << status.getDescription();
+        }
+        return {.success = status.isOk(), .errMsg = status.getDescription()};
+    }
+
+  private:
+    const std::shared_ptr<IBootControl> module_;
+};
+
+using namespace android::hardware::boot;
+
+class BootControlClientHIDL final : public BootControlClient {
+  public:
+    BootControlClientHIDL(android::sp<V1_0::IBootControl> module_v1,
+                          android::sp<V1_1::IBootControl> module_v1_1,
+                          android::sp<V1_2::IBootControl> module_v1_2)
+        : module_v1_(module_v1), module_v1_1_(module_v1_1), module_v1_2_(module_v1_2) {
+        CHECK(module_v1_ != nullptr);
+    }
+    BootControlVersion GetVersion() const override {
+        if (module_v1_2_ != nullptr) {
+            return BootControlVersion::BOOTCTL_V1_2;
+        } else if (module_v1_1_ != nullptr) {
+            return BootControlVersion::BOOTCTL_V1_1;
+        } else {
+            return BootControlVersion::BOOTCTL_V1_0;
+        }
+    }
+    int32_t GetNumSlots() const {
+        const auto ret = module_v1_->getNumberSlots();
+        if (!ret.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
+        }
+        return ret.withDefault(-1);
+    }
+
+    int32_t GetCurrentSlot() const {
+        const auto ret = module_v1_->getCurrentSlot();
+        if (!ret.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
+        }
+        return ret.withDefault(-1);
+    }
+
+    std::string GetSuffix(int32_t slot) const {
+        std::string suffix;
+        const auto ret = module_v1_->getSuffix(
+                slot,
+                [&](const ::android::hardware::hidl_string& slotSuffix) { suffix = slotSuffix; });
+        if (!ret.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
+                       << " failed " << ret.description();
+        }
+        return suffix;
+    }
+
+    std::optional<bool> IsSlotBootable(int32_t slot) const {
+        const auto ret = module_v1_->isSlotBootable(slot);
+        if (!ret.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
+                       << " failed " << ret.description();
+            return {};
+        }
+        const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
+        if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
+            return {};
+        }
+        return bool_result == V1_0::BoolResult::TRUE;
+    }
+
+    CommandResult MarkSlotUnbootable(int32_t slot) {
+        CommandResult result;
+        const auto ret =
+                module_v1_->setSlotAsUnbootable(slot, [&](const V1_0::CommandResult& error) {
+                    result.success = error.success;
+                    result.errMsg = error.errMsg;
+                });
+        if (!ret.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
+                       << " failed " << ret.description();
+        }
+        return result;
+    }
+
+    CommandResult SetActiveBootSlot(int32_t slot) {
+        CommandResult result;
+        const auto ret = module_v1_->setActiveBootSlot(slot, [&](const V1_0::CommandResult& error) {
+            result.success = error.success;
+            result.errMsg = error.errMsg;
+        });
+        if (!ret.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
+                       << " failed " << ret.description();
+        }
+        return result;
+    }
+
+    CommandResult MarkBootSuccessful() {
+        CommandResult result;
+        const auto ret = module_v1_->markBootSuccessful([&](const V1_0::CommandResult& error) {
+            result.success = error.success;
+            result.errMsg = error.errMsg;
+        });
+        if (!ret.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
+        }
+        return result;
+    }
+
+    std::optional<bool> IsSlotMarkedSuccessful(int32_t slot) const {
+        const auto ret = module_v1_->isSlotMarkedSuccessful(slot);
+        if (!ret.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
+                       << " failed " << ret.description();
+            return {};
+        }
+        const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
+        if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
+            return {};
+        }
+        return bool_result == V1_0::BoolResult::TRUE;
+    }
+
+    MergeStatus getSnapshotMergeStatus() const {
+        if (module_v1_1_ == nullptr) {
+            LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.1";
+            return MergeStatus::UNKNOWN;
+        }
+        const auto ret = module_v1_1_->getSnapshotMergeStatus();
+        if (!ret.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
+        }
+        return static_cast<MergeStatus>(
+                ret.withDefault(static_cast<V1_1::MergeStatus>(MergeStatus::UNKNOWN)));
+    }
+
+    CommandResult SetSnapshotMergeStatus(MergeStatus merge_status) {
+        if (module_v1_1_ == nullptr) {
+            return {.success = false,
+                    .errMsg = "setSnapshotMergeStatus is unsupported, requires at least boot v1.1"};
+        }
+        const auto ret =
+                module_v1_1_->setSnapshotMergeStatus(static_cast<V1_1::MergeStatus>(merge_status));
+        if (!ret.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")"
+                       << " failed " << ret.description();
+        }
+        return {.success = ret.isOk(), .errMsg = ret.description()};
+    }
+
+    int32_t GetActiveBootSlot() const {
+        if (module_v1_2_ == nullptr) {
+            LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.2";
+            return -1;
+        }
+        const auto ret = module_v1_2_->getActiveBootSlot();
+        if (!ret.isOk()) {
+            LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
+        }
+        return ret.withDefault(-1);
+    }
+
+  private:
+    android::sp<V1_0::IBootControl> module_v1_;
+    android::sp<V1_1::IBootControl> module_v1_1_;
+    android::sp<V1_2::IBootControl> module_v1_2_;
+};
+
+std::unique_ptr<BootControlClient> BootControlClient::WaitForService() {
+    const auto instance_name =
+            std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
+
+    if (AServiceManager_isDeclared(instance_name.c_str())) {
+        auto module = ::aidl::android::hardware::boot::IBootControl::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
+        if (module == nullptr) {
+            LOG(ERROR) << "AIDL " << instance_name
+                       << " is declared but waitForService returned nullptr.";
+            return nullptr;
+        }
+        LOG(INFO) << "Using AIDL version of IBootControl";
+        return std::make_unique<BootControlClientAidl>(module);
+    }
+    LOG(INFO) << "AIDL IBootControl not available, falling back to HIDL.";
+
+    android::sp<V1_0::IBootControl> v1_0_module;
+    android::sp<V1_1::IBootControl> v1_1_module;
+    android::sp<V1_2::IBootControl> v1_2_module;
+    v1_0_module = V1_0::IBootControl::getService();
+    if (v1_0_module == nullptr) {
+        LOG(ERROR) << "Error getting bootctrl v1.0 module.";
+        return nullptr;
+    }
+    v1_1_module = V1_1::IBootControl::castFrom(v1_0_module);
+    v1_2_module = V1_2::IBootControl::castFrom(v1_0_module);
+    if (v1_2_module != nullptr) {
+        LOG(INFO) << "Using HIDL version 1.2 of IBootControl";
+    } else if (v1_1_module != nullptr) {
+        LOG(INFO) << "Using HIDL version 1.1 of IBootControl";
+    } else {
+        LOG(INFO) << "Using HIDL version 1.0 of IBootControl";
+    }
+
+    return std::make_unique<BootControlClientHIDL>(v1_0_module, v1_1_module, v1_2_module);
+}
+
+}  // namespace android::hal
diff --git a/boot/aidl/client/include/BootControlClient.h b/boot/aidl/client/include/BootControlClient.h
new file mode 100644
index 0000000..472e82e
--- /dev/null
+++ b/boot/aidl/client/include/BootControlClient.h
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#ifndef __BOOT_CONTROL_CLIENT_H_
+#define __BOOT_CONTROL_CLIENT_H_
+
+#include <aidl/android/hardware/boot/MergeStatus.h>
+
+#include <stdint.h>
+
+#include <memory>
+#include <optional>
+
+namespace android::hal {
+
+struct CommandResult {
+    bool success;
+    std::string errMsg;
+    constexpr bool IsOk() const { return success; }
+};
+
+enum class BootControlVersion { BOOTCTL_V1_0, BOOTCTL_V1_1, BOOTCTL_V1_2, BOOTCTL_AIDL };
+
+class BootControlClient {
+  public:
+    using MergeStatus = aidl::android::hardware::boot::MergeStatus;
+    virtual ~BootControlClient() = default;
+    virtual BootControlVersion GetVersion() const = 0;
+    // Return the number of update slots in the system. A system will normally
+    // have two slots, named "A" and "B" in the documentation, but sometimes
+    // images running from other media can have only one slot, like some USB
+    // image. Systems with only one slot won't be able to update.
+    [[nodiscard]] virtual int32_t GetNumSlots() const = 0;
+
+    // Return the slot where we are running the system from. On success, the
+    // result is a number between 0 and GetNumSlots() - 1. Otherwise, log an error
+    // and return kInvalidSlot.
+    [[nodiscard]] virtual int32_t GetCurrentSlot() const = 0;
+
+    // Return string suffix for input slot. Usually, for slot 0 the suffix is _a, and for slot 1 the
+    // suffix is _b.
+    [[nodiscard]] virtual std::string GetSuffix(int32_t slot) const = 0;
+
+    // Returns whether the passed |slot| is marked as bootable. Returns false if
+    // the slot is invalid.
+    [[nodiscard]] virtual std::optional<bool> IsSlotBootable(int32_t slot) const = 0;
+
+    // Mark the specified slot unbootable. No other slot flags are modified.
+    // Returns true on success.
+    [[nodiscard]] virtual CommandResult MarkSlotUnbootable(int32_t slot) = 0;
+
+    // Set the passed |slot| as the preferred boot slot. Returns whether it
+    // succeeded setting the active slot. If succeeded, on next boot the
+    // bootloader will attempt to load the |slot| marked as active. Note that this
+    // method doesn't change the value of GetCurrentSlot() on the current boot.
+    // Return true if operation succeeded.
+    [[nodiscard]] virtual CommandResult SetActiveBootSlot(int32_t slot) = 0;
+
+    // Check if |slot| is marked boot successfully. Return empty optional if the RPC call failed.
+    [[nodiscard]] virtual std::optional<bool> IsSlotMarkedSuccessful(int32_t slot) const = 0;
+
+    // Mark boot as successful. Return an error message if operation failed.
+    [[nodiscard]] virtual CommandResult MarkBootSuccessful() = 0;
+
+    // Added in IBootControl v1.1
+    // Return the current merge status.
+    [[nodiscard]] virtual MergeStatus getSnapshotMergeStatus() const = 0;
+
+    // Set snapshot merge status, return true if succeeded.
+    [[nodiscard]] virtual CommandResult SetSnapshotMergeStatus(MergeStatus status) = 0;
+
+    // Added in IBootControl v1.2
+    // Get the active slot. In other words, the slot which will be used on
+    // next system reboot. This should match the |slot| parameter of last
+    // successful call to |SetActiveBootSlot|.
+    // Return 0xFFFFFFFF if underlying HAL doesn't support this operation.
+    [[nodiscard]] virtual int32_t GetActiveBootSlot() const = 0;
+
+    [[nodiscard]] static std::unique_ptr<BootControlClient> WaitForService();
+};
+
+}  // namespace android::hal
+
+#endif
diff --git a/boot/aidl/default/Android.bp b/boot/aidl/default/Android.bp
new file mode 100644
index 0000000..dcb40db
--- /dev/null
+++ b/boot/aidl/default/Android.bp
@@ -0,0 +1,55 @@
+//
+// 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_defaults {
+    name: "android.hardware.boot-service_common",
+    relative_install_path: "hw",
+    defaults: ["libboot_control_defaults"],
+    vintf_fragments: ["android.hardware.boot-service.default.xml"],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "android.hardware.boot@1.1",
+        "android.hardware.boot-V1-ndk",
+    ],
+    static_libs: [
+        "libboot_control",
+    ],
+    srcs: ["main.cpp", "BootControl.cpp"],
+}
+
+cc_binary {
+    name: "android.hardware.boot-service.default",
+    defaults: ["android.hardware.boot-service_common"],
+    init_rc: ["android.hardware.boot-service.default.rc"],
+    vendor: true,
+}
+
+cc_binary {
+    name: "android.hardware.boot-service.default_recovery",
+    defaults: ["android.hardware.boot-service_common"],
+    init_rc: ["android.hardware.boot-service.default_recovery.rc"],
+    recovery: true,
+}
diff --git a/boot/aidl/default/BootControl.cpp b/boot/aidl/default/BootControl.cpp
new file mode 100644
index 0000000..b73c94d
--- /dev/null
+++ b/boot/aidl/default/BootControl.cpp
@@ -0,0 +1,154 @@
+/*
+ * 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 "BootControl.h"
+#include <cstdint>
+
+#include <android-base/logging.h>
+
+using HIDLMergeStatus = ::android::bootable::BootControl::MergeStatus;
+using ndk::ScopedAStatus;
+
+namespace aidl::android::hardware::boot {
+
+BootControl::BootControl() {
+    CHECK(impl_.Init());
+}
+
+ScopedAStatus BootControl::getActiveBootSlot(int32_t* _aidl_return) {
+    *_aidl_return = impl_.GetActiveBootSlot();
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus BootControl::getCurrentSlot(int32_t* _aidl_return) {
+    *_aidl_return = impl_.GetCurrentSlot();
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus BootControl::getNumberSlots(int32_t* _aidl_return) {
+    *_aidl_return = impl_.GetNumberSlots();
+    return ScopedAStatus::ok();
+}
+
+namespace {
+
+static constexpr MergeStatus ToAIDLMergeStatus(HIDLMergeStatus status) {
+    switch (status) {
+        case HIDLMergeStatus::NONE:
+            return MergeStatus::NONE;
+        case HIDLMergeStatus::UNKNOWN:
+            return MergeStatus::UNKNOWN;
+        case HIDLMergeStatus::SNAPSHOTTED:
+            return MergeStatus::SNAPSHOTTED;
+        case HIDLMergeStatus::MERGING:
+            return MergeStatus::MERGING;
+        case HIDLMergeStatus::CANCELLED:
+            return MergeStatus::CANCELLED;
+    }
+}
+
+static constexpr HIDLMergeStatus ToHIDLMergeStatus(MergeStatus status) {
+    switch (status) {
+        case MergeStatus::NONE:
+            return HIDLMergeStatus::NONE;
+        case MergeStatus::UNKNOWN:
+            return HIDLMergeStatus::UNKNOWN;
+        case MergeStatus::SNAPSHOTTED:
+            return HIDLMergeStatus::SNAPSHOTTED;
+        case MergeStatus::MERGING:
+            return HIDLMergeStatus::MERGING;
+        case MergeStatus::CANCELLED:
+            return HIDLMergeStatus::CANCELLED;
+    }
+}
+
+}
+
+ScopedAStatus BootControl::getSnapshotMergeStatus(MergeStatus* _aidl_return) {
+    *_aidl_return = ToAIDLMergeStatus(impl_.GetSnapshotMergeStatus());
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus BootControl::getSuffix(int32_t in_slot, std::string* _aidl_return) {
+    if (!impl_.IsValidSlot(in_slot)) {
+        // Old HIDL hal returns empty string for invalid slots. We should maintain this behavior in
+        // AIDL for compatibility.
+        _aidl_return->clear();
+    } else {
+        *_aidl_return = impl_.GetSuffix(in_slot);
+    }
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus BootControl::isSlotBootable(int32_t in_slot, bool* _aidl_return) {
+    if (!impl_.IsValidSlot(in_slot)) {
+        return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                INVALID_SLOT, (std::string("Invalid slot ") + std::to_string(in_slot)).c_str());
+    }
+    *_aidl_return = impl_.IsSlotBootable(in_slot);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus BootControl::isSlotMarkedSuccessful(int32_t in_slot, bool* _aidl_return) {
+    if (!impl_.IsValidSlot(in_slot)) {
+        return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                INVALID_SLOT, (std::string("Invalid slot ") + std::to_string(in_slot)).c_str());
+    }
+    *_aidl_return = impl_.IsSlotMarkedSuccessful(in_slot);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus BootControl::markBootSuccessful() {
+    if (!impl_.MarkBootSuccessful()) {
+        return ScopedAStatus::fromServiceSpecificErrorWithMessage(COMMAND_FAILED,
+                                                                  "Operation failed");
+    }
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus BootControl::setActiveBootSlot(int32_t in_slot) {
+    if (!impl_.IsValidSlot(in_slot)) {
+        return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                INVALID_SLOT, (std::string("Invalid slot ") + std::to_string(in_slot)).c_str());
+    }
+    if (!impl_.SetActiveBootSlot(in_slot)) {
+        return ScopedAStatus::fromServiceSpecificErrorWithMessage(COMMAND_FAILED,
+                                                                  "Operation failed");
+    }
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus BootControl::setSlotAsUnbootable(int32_t in_slot) {
+    if (!impl_.IsValidSlot(in_slot)) {
+        return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                INVALID_SLOT, (std::string("Invalid slot ") + std::to_string(in_slot)).c_str());
+    }
+    if (!impl_.SetSlotAsUnbootable(in_slot)) {
+        return ScopedAStatus::fromServiceSpecificErrorWithMessage(COMMAND_FAILED,
+                                                                  "Operation failed");
+    }
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus BootControl::setSnapshotMergeStatus(MergeStatus in_status) {
+    if (!impl_.SetSnapshotMergeStatus(ToHIDLMergeStatus(in_status))) {
+        return ScopedAStatus::fromServiceSpecificErrorWithMessage(COMMAND_FAILED,
+                                                                  "Operation failed");
+    }
+    return ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::boot
diff --git a/boot/aidl/default/BootControl.h b/boot/aidl/default/BootControl.h
new file mode 100644
index 0000000..54cd32d
--- /dev/null
+++ b/boot/aidl/default/BootControl.h
@@ -0,0 +1,45 @@
+/*
+ * 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 <aidl/android/hardware/boot/BnBootControl.h>
+#include <libboot_control/libboot_control.h>
+
+namespace aidl::android::hardware::boot {
+
+class BootControl final : public BnBootControl {
+  public:
+    BootControl();
+    ::ndk::ScopedAStatus getActiveBootSlot(int32_t* _aidl_return) override;
+    ::ndk::ScopedAStatus getCurrentSlot(int32_t* _aidl_return) override;
+    ::ndk::ScopedAStatus getNumberSlots(int32_t* _aidl_return) override;
+    ::ndk::ScopedAStatus getSnapshotMergeStatus(
+            ::aidl::android::hardware::boot::MergeStatus* _aidl_return) override;
+    ::ndk::ScopedAStatus getSuffix(int32_t in_slot, std::string* _aidl_return) override;
+    ::ndk::ScopedAStatus isSlotBootable(int32_t in_slot, bool* _aidl_return) override;
+    ::ndk::ScopedAStatus isSlotMarkedSuccessful(int32_t in_slot, bool* _aidl_return) override;
+    ::ndk::ScopedAStatus markBootSuccessful() override;
+    ::ndk::ScopedAStatus setActiveBootSlot(int32_t in_slot) override;
+    ::ndk::ScopedAStatus setSlotAsUnbootable(int32_t in_slot) override;
+    ::ndk::ScopedAStatus setSnapshotMergeStatus(
+            ::aidl::android::hardware::boot::MergeStatus in_status) override;
+
+  private:
+    ::android::bootable::BootControl impl_;
+};
+
+}  // namespace aidl::android::hardware::boot
diff --git a/boot/aidl/default/android.hardware.boot-service.default.rc b/boot/aidl/default/android.hardware.boot-service.default.rc
new file mode 100644
index 0000000..589f803
--- /dev/null
+++ b/boot/aidl/default/android.hardware.boot-service.default.rc
@@ -0,0 +1,5 @@
+service vendor.boot-default /vendor/bin/hw/android.hardware.boot-service.default
+    class early_hal
+    user root
+    group root
+
diff --git a/boot/aidl/default/android.hardware.boot-service.default.xml b/boot/aidl/default/android.hardware.boot-service.default.xml
new file mode 100644
index 0000000..23ccc4e
--- /dev/null
+++ b/boot/aidl/default/android.hardware.boot-service.default.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.boot</name>
+        <fqname>IBootControl/default</fqname>
+    </hal>
+</manifest>
diff --git a/boot/aidl/default/android.hardware.boot-service.default_recovery.rc b/boot/aidl/default/android.hardware.boot-service.default_recovery.rc
new file mode 100644
index 0000000..cb08a39
--- /dev/null
+++ b/boot/aidl/default/android.hardware.boot-service.default_recovery.rc
@@ -0,0 +1,7 @@
+service vendor.boot-default /system/bin/hw/android.hardware.boot-service.default_recovery
+    class early_hal
+    user root
+    group root
+    seclabel u:r:hal_bootctl_default:s0
+    interface aidl android.hardware.boot.IBootControl/default
+
diff --git a/boot/aidl/default/main.cpp b/boot/aidl/default/main.cpp
new file mode 100644
index 0000000..70b284e
--- /dev/null
+++ b/boot/aidl/default/main.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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 "BootControl.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::boot::BootControl;
+using aidl::android::hardware::boot::IBootControl;
+
+int main(int, char* argv[]) {
+    android::base::InitLogging(argv, android::base::KernelLogger);
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    std::shared_ptr<IBootControl> service = ndk::SharedRefBase::make<BootControl>();
+
+    const std::string instance = std::string(BootControl::descriptor) + "/default";
+    auto status = AServiceManager_addService(service->asBinder().get(), instance.c_str());
+    CHECK_EQ(status, STATUS_OK) << "Failed to add service " << instance << " " << status;
+    LOG(INFO) << "IBootControl AIDL service running...";
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reach
+}
diff --git a/boot/aidl/vts/functional/Android.bp b/boot/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..e46cbef
--- /dev/null
+++ b/boot/aidl/vts/functional/Android.bp
@@ -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 {
+    // 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: "VtsHalBootAidlTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static"
+    ],
+    srcs: ["VtsHalBootAidlTargetTest.cpp"],
+    static_libs: [
+        "android.hardware.boot-V1-ndk",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libvintf",
+    ],
+    test_suites: ["general-tests", "vts"],
+}
diff --git a/boot/aidl/vts/functional/OWNERS b/boot/aidl/vts/functional/OWNERS
new file mode 100644
index 0000000..bc813d8
--- /dev/null
+++ b/boot/aidl/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 30545
+zhangkelvin@google.com
diff --git a/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp b/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp
new file mode 100644
index 0000000..ab3c789
--- /dev/null
+++ b/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp
@@ -0,0 +1,194 @@
+/*
+ * 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 <android-base/logging.h>
+
+#include <cutils/properties.h>
+
+#include <aidl/android/hardware/boot/IBootControl.h>
+
+#include <aidl/Vintf.h>
+#include <android/binder_manager.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <unordered_set>
+
+using aidl::android::hardware::boot::IBootControl;
+using std::string;
+using std::unordered_set;
+
+// The main test class for the Boot HIDL HAL.
+class BootHidlTest : public ::testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        const auto instance_name = GetParam();
+        ASSERT_TRUE(AServiceManager_isDeclared(instance_name.c_str()))
+                << " instance " << instance_name << " not declared.";
+        boot = ::aidl::android::hardware::boot::IBootControl::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
+        ASSERT_NE(boot, nullptr);
+    }
+
+    std::shared_ptr<IBootControl> boot;
+};
+
+// validity check Boot::getNumberSlots().
+TEST_P(BootHidlTest, GetNumberSlots) {
+    int32_t slots{};
+    boot->getNumberSlots(&slots);
+    ASSERT_LE(2, slots);
+}
+
+// validity check Boot::getCurrentSlot().
+TEST_P(BootHidlTest, GetCurrentSlot) {
+    int curSlot = -1;
+    boot->getCurrentSlot(&curSlot);
+    int slots = 0;
+    boot->getNumberSlots(&slots);
+    ASSERT_LT(curSlot, slots);
+}
+
+// validity check Boot::markBootSuccessful().
+TEST_P(BootHidlTest, MarkBootSuccessful) {
+    const auto result = boot->markBootSuccessful();
+    ASSERT_TRUE(result.isOk());
+    int curSlot = 0;
+    boot->getCurrentSlot(&curSlot);
+    bool ret = false;
+    boot->isSlotMarkedSuccessful(curSlot, &ret);
+    ASSERT_TRUE(ret);
+}
+
+TEST_P(BootHidlTest, SetActiveBootSlot) {
+    int curSlot = -1;
+    boot->getCurrentSlot(&curSlot);
+    ASSERT_GE(curSlot, 0);
+    int otherSlot = curSlot ? 0 : 1;
+    bool otherBootable = true;
+    boot->isSlotBootable(otherSlot, &otherBootable);
+
+    for (int s = 0; s < 2; s++) {
+        const auto result = boot->setActiveBootSlot(s);
+        ASSERT_TRUE(result.isOk());
+    }
+    {
+        // Restore original flags to avoid problems on reboot
+        auto result = boot->setActiveBootSlot(curSlot);
+        ASSERT_TRUE(result.isOk());
+
+        if (!otherBootable) {
+            const auto result = boot->setSlotAsUnbootable(otherSlot);
+            ASSERT_TRUE(result.isOk());
+        }
+
+        result = boot->markBootSuccessful();
+        ASSERT_TRUE(result.isOk());
+    }
+    {
+        int slots = 0;
+        boot->getNumberSlots(&slots);
+        const auto result = boot->setActiveBootSlot(slots);
+        ASSERT_FALSE(result.isOk()) << "setActiveBootSlot on invalid slot should fail";
+    }
+}
+
+TEST_P(BootHidlTest, SetSlotAsUnbootable) {
+    int curSlot = -1;
+    boot->getCurrentSlot(&curSlot);
+    ASSERT_GE(curSlot, 0);
+    int otherSlot = curSlot ? 0 : 1;
+    bool otherBootable = false;
+    boot->isSlotBootable(otherSlot, &otherBootable);
+    {
+        auto result = boot->setSlotAsUnbootable(otherSlot);
+        ASSERT_TRUE(result.isOk());
+        boot->isSlotBootable(otherSlot, &otherBootable);
+        ASSERT_FALSE(otherBootable);
+
+        // Restore original flags to avoid problems on reboot
+        if (otherBootable) {
+            result = boot->setActiveBootSlot(otherSlot);
+            ASSERT_TRUE(result.isOk());
+        }
+        result = boot->setActiveBootSlot(curSlot);
+        ASSERT_TRUE(result.isOk());
+        result = boot->markBootSuccessful();
+        ASSERT_TRUE(result.isOk());
+    }
+    {
+        int32_t slots = 0;
+        boot->getNumberSlots(&slots);
+        const auto result = boot->setSlotAsUnbootable(slots);
+        ASSERT_FALSE(result.isOk());
+    }
+}
+
+// validity check Boot::isSlotBootable() on good and bad inputs.
+TEST_P(BootHidlTest, IsSlotBootable) {
+    for (int s = 0; s < 2; s++) {
+        bool bootable = false;
+        const auto res = boot->isSlotBootable(s, &bootable);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+    }
+    int32_t slots = 0;
+    boot->getNumberSlots(&slots);
+    bool bootable = false;
+    const auto res = boot->isSlotBootable(slots, &bootable);
+    ASSERT_FALSE(res.isOk());
+}
+
+// validity check Boot::isSlotMarkedSuccessful() on good and bad inputs.
+TEST_P(BootHidlTest, IsSlotMarkedSuccessful) {
+    for (int32_t s = 0; s < 2; s++) {
+        bool isSuccess = false;
+        const auto res = boot->isSlotMarkedSuccessful(s, &isSuccess);
+    }
+    int32_t slots = 0;
+    boot->getNumberSlots(&slots);
+    bool isSuccess = false;
+    const auto res = boot->isSlotMarkedSuccessful(slots, &isSuccess);
+    ASSERT_FALSE(res.isOk());
+}
+
+// validity check Boot::getSuffix() on good and bad inputs.
+TEST_P(BootHidlTest, GetSuffix) {
+    string suffixStr;
+    unordered_set<string> suffixes;
+    int numSlots = 0;
+    boot->getNumberSlots(&numSlots);
+    for (int32_t i = 0; i < numSlots; i++) {
+        std::string suffix;
+        const auto result = boot->getSuffix(i, &suffixStr);
+        ASSERT_TRUE(result.isOk());
+        ASSERT_EQ('_', suffixStr[0]);
+        ASSERT_LE((unsigned)2, suffixStr.size());
+        suffixes.insert(suffixStr);
+    }
+    // All suffixes should be unique
+    ASSERT_EQ(numSlots, suffixes.size());
+    {
+        const string emptySuffix = "";
+        const auto result = boot->getSuffix(numSlots, &suffixStr);
+        ASSERT_TRUE(result.isOk());
+        ASSERT_EQ(suffixStr, emptySuffix);
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, BootHidlTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IBootControl::descriptor)));
diff --git a/broadcastradio/1.0/default/OWNERS b/broadcastradio/1.0/default/OWNERS
index 57e6592..302fdd7 100644
--- a/broadcastradio/1.0/default/OWNERS
+++ b/broadcastradio/1.0/default/OWNERS
@@ -1,3 +1,4 @@
-elaurent@google.com
-mnaganov@google.com
-twasilczyk@google.com
+xuweilin@google.com
+oscarazu@google.com
+ericjeong@google.com
+keunyoung@google.com
diff --git a/broadcastradio/1.0/vts/functional/OWNERS b/broadcastradio/1.0/vts/functional/OWNERS
index 778c4a2..aa19d6a 100644
--- a/broadcastradio/1.0/vts/functional/OWNERS
+++ b/broadcastradio/1.0/vts/functional/OWNERS
@@ -1,2 +1,5 @@
 # Bug component: 533946
+xuweilin@google.com
 oscarazu@google.com
+ericjeong@google.com
+keunyoung@google.com
diff --git a/broadcastradio/1.1/default/OWNERS b/broadcastradio/1.1/default/OWNERS
index 136b607..259b91e 100644
--- a/broadcastradio/1.1/default/OWNERS
+++ b/broadcastradio/1.1/default/OWNERS
@@ -1,3 +1,5 @@
 # Automotive team
-egranata@google.com
-twasilczyk@google.com
+xuweilin@google.com
+oscarazu@google.com
+ericjeong@google.com
+keunyoung@google.com
diff --git a/broadcastradio/1.1/vts/OWNERS b/broadcastradio/1.1/vts/OWNERS
index 2c21c25..aa19d6a 100644
--- a/broadcastradio/1.1/vts/OWNERS
+++ b/broadcastradio/1.1/vts/OWNERS
@@ -1,3 +1,5 @@
 # Bug component: 533946
+xuweilin@google.com
 oscarazu@google.com
+ericjeong@google.com
 keunyoung@google.com
diff --git a/broadcastradio/2.0/default/OWNERS b/broadcastradio/2.0/default/OWNERS
index 136b607..259b91e 100644
--- a/broadcastradio/2.0/default/OWNERS
+++ b/broadcastradio/2.0/default/OWNERS
@@ -1,3 +1,5 @@
 # Automotive team
-egranata@google.com
-twasilczyk@google.com
+xuweilin@google.com
+oscarazu@google.com
+ericjeong@google.com
+keunyoung@google.com
diff --git a/broadcastradio/2.0/vts/OWNERS b/broadcastradio/2.0/vts/OWNERS
index 1ff7407..09690ef 100644
--- a/broadcastradio/2.0/vts/OWNERS
+++ b/broadcastradio/2.0/vts/OWNERS
@@ -1,6 +1,8 @@
 # Automotive team
-egranata@google.com
-twasilczyk@google.com
+xuweilin@google.com
+oscarazu@google.com
+ericjeong@google.com
+keunyoung@google.com
 
 # VTS team
 dshi@google.com
diff --git a/broadcastradio/2.0/vts/functional/OWNERS b/broadcastradio/2.0/vts/functional/OWNERS
index 2c21c25..aa19d6a 100644
--- a/broadcastradio/2.0/vts/functional/OWNERS
+++ b/broadcastradio/2.0/vts/functional/OWNERS
@@ -1,3 +1,5 @@
 # Bug component: 533946
+xuweilin@google.com
 oscarazu@google.com
+ericjeong@google.com
 keunyoung@google.com
diff --git a/broadcastradio/common/OWNERS b/broadcastradio/common/OWNERS
index 136b607..259b91e 100644
--- a/broadcastradio/common/OWNERS
+++ b/broadcastradio/common/OWNERS
@@ -1,3 +1,5 @@
 # Automotive team
-egranata@google.com
-twasilczyk@google.com
+xuweilin@google.com
+oscarazu@google.com
+ericjeong@google.com
+keunyoung@google.com
diff --git a/camera/common/aidl/Android.bp b/camera/common/aidl/Android.bp
index 19de22d..d21ae58 100644
--- a/camera/common/aidl/Android.bp
+++ b/camera/common/aidl/Android.bp
@@ -19,11 +19,6 @@
         java: {
             enabled: false,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/camera/device/aidl/Android.bp b/camera/device/aidl/Android.bp
index afc6b8d..365a5ff 100644
--- a/camera/device/aidl/Android.bp
+++ b/camera/device/aidl/Android.bp
@@ -27,11 +27,6 @@
             sdk_version: "module_current",
             enabled: false,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/camera/device/aidl/android/hardware/camera/device/StreamBuffer.aidl b/camera/device/aidl/android/hardware/camera/device/StreamBuffer.aidl
index e487494..29fec68 100644
--- a/camera/device/aidl/android/hardware/camera/device/StreamBuffer.aidl
+++ b/camera/device/aidl/android/hardware/camera/device/StreamBuffer.aidl
@@ -33,8 +33,8 @@
 parcelable StreamBuffer {
     /**
      * The ID of the stream this buffer is associated with. -1 indicates an
-     * invalid (empty) StreamBuffer, in which case buffer must also point to
-     * null and bufferId must be 0.
+     * invalid (empty) StreamBuffer, in which case buffer must be empty
+     * and bufferId must be 0.
      */
     int streamId;
 
@@ -48,7 +48,7 @@
      * corresponding stream is removed from stream configuration or until camera
      * device session is closed. After the first time a buffer is introduced to
      * HAL, in the future camera service must refer to the same buffer using
-     * only bufferId, and keep the buffer handle null.
+     * only bufferId, and keep the buffer handle empty.
      */
     long bufferId;
 
@@ -59,10 +59,10 @@
      * is not seen by the HAL before, this buffer handle is guaranteed to be a
      * valid handle to a graphics buffer, with dimensions and format matching
      * that of the stream. If the bufferId has been sent to the HAL before, this
-     * buffer handle must be null and HAL must look up the actual buffer handle
+     * buffer handle must be empty and HAL must look up the actual buffer handle
      * to use from its own bufferId to buffer handle map.
      *
-     * For StreamBuffers returned in a CaptureResult, this must be null, since
+     * For StreamBuffers returned in a CaptureResult, this must be empty, since
      * the handle to the buffer is already known to the client (since the client
      * sent it in the matching CaptureRequest), and the handle can be identified
      * by the combination of frame number and stream ID.
@@ -81,11 +81,11 @@
      * The acquire sync fence for this buffer. The HAL must wait on this fence
      * fd before attempting to read from or write to this buffer.
      *
-     * In a buffer included in a CaptureRequest, the client may set this to null
+     * In a buffer included in a CaptureRequest, the client may leave this empty
      * to indicate that no waiting is necessary for this buffer.
      *
      * When the HAL returns an input or output buffer to the framework with
-     * processCaptureResult(), the acquireFence must be set to null. If the HAL
+     * processCaptureResult(), the acquireFence must be empty. If the HAL
      * never waits on the acquireFence due to an error in filling or reading a
      * buffer, when calling processCaptureResult() the HAL must set the
      * releaseFence of the buffer to be the acquireFence passed to it by the
@@ -97,17 +97,17 @@
     /**
      * The release sync fence for this buffer. The HAL must set this to a valid
      * fence fd when returning the input buffer or output buffers to the client
-     * in a CaptureResult, or set it to null to indicate that no waiting is
+     * in a CaptureResult, or leave it empty to indicate that no waiting is
      * required for this buffer.
      *
-     * The client must set this to be null for all buffers included in a
+     * The client must leave this empty for all buffers included in a
      * processCaptureRequest call.
      *
      * After signaling the releaseFence for this buffer, the HAL
      * must not make any further attempts to access this buffer as the
      * ownership has been fully transferred back to the client.
      *
-     * If this is null, then the ownership of this buffer is transferred back
+     * If this is empty, then the ownership of the buffer is transferred back
      * immediately upon the call of processCaptureResult.
      */
     NativeHandle releaseFence;
diff --git a/camera/metadata/aidl/Android.bp b/camera/metadata/aidl/Android.bp
index 31d4b4d..301a943 100644
--- a/camera/metadata/aidl/Android.bp
+++ b/camera/metadata/aidl/Android.bp
@@ -19,11 +19,6 @@
         java: {
             enabled: false,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 6866776..b0ae20e 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -7883,6 +7883,7 @@
             }
         }
 
+        camera_metadata_t* staticMetadata;
         camera_metadata_ro_entry physicalMultiResStreamConfigs;
         camera_metadata_ro_entry physicalStreamConfigs;
         camera_metadata_ro_entry physicalMaxResolutionStreamConfigs;
@@ -7901,8 +7902,9 @@
 
             ret = subDevice->getCameraCharacteristics([&](auto status, const auto& chars) {
                 ASSERT_EQ(Status::OK, status);
-                const camera_metadata_t* staticMetadata =
-                        reinterpret_cast<const camera_metadata_t*>(chars.data());
+                staticMetadata = clone_camera_metadata(
+                        reinterpret_cast<const camera_metadata_t*>(chars.data()));
+                ASSERT_NE(nullptr, staticMetadata);
                 rc = getSystemCameraKind(staticMetadata, &physSystemCameraKind);
                 ASSERT_EQ(rc, Status::OK);
                 // Make sure that the system camera kind of a non-hidden
@@ -7936,7 +7938,9 @@
                         verifyCameraCharacteristics(status, chars);
                         verifyMonochromeCharacteristics(chars, deviceVersion);
 
-                        auto staticMetadata = (const camera_metadata_t*)chars.data();
+                        staticMetadata = clone_camera_metadata(
+                                reinterpret_cast<const camera_metadata_t*>(chars.data()));
+                        ASSERT_NE(nullptr, staticMetadata);
                         retcode = find_camera_metadata_ro_entry(
                                 staticMetadata, ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
                         bool subCameraHasZoomRatioRange = (0 == retcode && entry.count == 2);
@@ -8064,6 +8068,7 @@
                 }
             }
         }
+        free_camera_metadata(staticMetadata);
     }
 
     // If a multi-resolution stream is supported, there must be at least one
diff --git a/camera/provider/aidl/Android.bp b/camera/provider/aidl/Android.bp
index f082bce..87a94b2 100644
--- a/camera/provider/aidl/Android.bp
+++ b/camera/provider/aidl/Android.bp
@@ -25,11 +25,6 @@
         cpp: {
             enabled: false,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp
index 20f32bf..2c2f1b2 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -1181,6 +1181,7 @@
         camera_metadata_ro_entry physicalMultiResStreamConfigs;
         camera_metadata_ro_entry physicalStreamConfigs;
         camera_metadata_ro_entry physicalMaxResolutionStreamConfigs;
+        CameraMetadata physChars;
         bool isUltraHighRes = false;
         std::unordered_set<int32_t> subCameraPrivacyTestPatterns;
         if (isPublicId) {
@@ -1189,12 +1190,11 @@
             ASSERT_TRUE(ret.isOk());
             ASSERT_NE(subDevice, nullptr);
 
-            CameraMetadata subDeviceChars;
-            ret = subDevice->getCameraCharacteristics(&subDeviceChars);
+            ret = subDevice->getCameraCharacteristics(&physChars);
             ASSERT_TRUE(ret.isOk());
 
             const camera_metadata_t* staticMetadata =
-                    reinterpret_cast<const camera_metadata_t*>(subDeviceChars.metadata.data());
+                    reinterpret_cast<const camera_metadata_t*>(physChars.metadata.data());
             retStatus = getSystemCameraKind(staticMetadata, &physSystemCameraKind);
             ASSERT_EQ(retStatus, Status::OK);
 
@@ -1215,7 +1215,6 @@
             getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
         } else {
             // Check camera characteristics for hidden camera id
-            CameraMetadata physChars;
             ndk::ScopedAStatus ret =
                     device->getPhysicalCameraCharacteristics(physicalId, &physChars);
             ASSERT_TRUE(ret.isOk());
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index 549d970..43f8c4d 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -30,7 +30,7 @@
         ndk: {
             apex_available: [
                 "//apex_available:platform",
-                "com.android.bluetooth",
+                "com.android.btservices",
                 "com.android.media.swcodec",
                 "com.android.neuralnetworks",
             ],
diff --git a/common/fmq/aidl/Android.bp b/common/fmq/aidl/Android.bp
index 6fd4200..a85597c 100644
--- a/common/fmq/aidl/Android.bp
+++ b/common/fmq/aidl/Android.bp
@@ -32,7 +32,7 @@
         ndk: {
             apex_available: [
                 "//apex_available:platform",
-                "com.android.bluetooth",
+                "com.android.btservices",
             ],
             min_sdk_version: "29",
         },
diff --git a/common/support/NativeHandle.cpp b/common/support/NativeHandle.cpp
index 321d7a8..126ef2e 100644
--- a/common/support/NativeHandle.cpp
+++ b/common/support/NativeHandle.cpp
@@ -22,6 +22,13 @@
 
 using aidl::android::hardware::common::NativeHandle;
 
+/**
+ * Checks if a NativeHandle is null
+ */
+bool isAidlNativeHandleEmpty(const NativeHandle& handle) {
+    return handle.fds.empty() && handle.ints.empty();
+}
+
 static native_handle_t* fromAidl(const NativeHandle& handle, bool doDup) {
     native_handle_t* to = native_handle_create(handle.fds.size(), handle.ints.size());
     if (!to) return nullptr;
diff --git a/common/support/include/aidlcommonsupport/NativeHandle.h b/common/support/include/aidlcommonsupport/NativeHandle.h
index 10eecba..b5ea1dd 100644
--- a/common/support/include/aidlcommonsupport/NativeHandle.h
+++ b/common/support/include/aidlcommonsupport/NativeHandle.h
@@ -22,6 +22,11 @@
 namespace android {
 
 /**
+ * Checks if a NativeHandle is empty.
+ */
+bool isAidlNativeHandleEmpty(const aidl::android::hardware::common::NativeHandle& handle);
+
+/**
  * Creates a libcutils native handle from an AIDL native handle, but it does not
  * dup internally, so it will contain the same FDs as the handle itself. The
  * result should be deleted with native_handle_delete.
diff --git a/common/support/test.cpp b/common/support/test.cpp
index 2359277..9b79581 100644
--- a/common/support/test.cpp
+++ b/common/support/test.cpp
@@ -62,6 +62,7 @@
 
 TEST(ConvertNativeHandle, MakeFromAidlEmpty) {
     NativeHandle handle;
+    EXPECT_TRUE(isAidlNativeHandleEmpty(handle));
     native_handle_t* to = makeFromAidl(handle);
     checkEq(handle, to, false /*exceptFds*/);
     // no native_handle_close b/c fds are owned by NativeHandle
@@ -70,6 +71,7 @@
 
 TEST(ConvertNativeHandle, MakeFromAidl) {
     NativeHandle handle = makeTestAidlHandle();
+    EXPECT_FALSE(isAidlNativeHandleEmpty(handle));
     native_handle_t* to = makeFromAidl(handle);
     checkEq(handle, to, false /*exceptFds*/);
     // no native_handle_close b/c fds are owned by NativeHandle
@@ -106,6 +108,7 @@
 TEST(ConvertNativeHandle, MakeToAidlEmpty) {
     native_handle_t* handle = native_handle_create(0, 0);
     NativeHandle to = makeToAidl(handle);
+    EXPECT_TRUE(isAidlNativeHandleEmpty(to));
     checkEq(to, handle, false /*exceptFds*/);
     // no native_handle_close b/c fds are owned by NativeHandle now
     EXPECT_EQ(0, native_handle_delete(handle));
@@ -114,6 +117,7 @@
 TEST(ConvertNativeHandle, MakeToAidl) {
     native_handle_t* handle = makeTestLibcutilsHandle();
     NativeHandle to = makeToAidl(handle);
+    EXPECT_FALSE(isAidlNativeHandleEmpty(to));
     checkEq(to, handle, false /*exceptFds*/);
     // no native_handle_close b/c fds are owned by NativeHandle now
     EXPECT_EQ(0, native_handle_delete(handle));
@@ -122,6 +126,7 @@
 TEST(ConvertNativeHandle, DupToAidlEmpty) {
     native_handle_t* handle = native_handle_create(0, 0);
     NativeHandle to = dupToAidl(handle);
+    EXPECT_TRUE(isAidlNativeHandleEmpty(to));
     checkEq(to, handle, true /*exceptFds*/);
     EXPECT_EQ(0, native_handle_close(handle));
     EXPECT_EQ(0, native_handle_delete(handle));
@@ -130,6 +135,7 @@
 TEST(ConvertNativeHandle, DupToAidl) {
     native_handle_t* handle = makeTestLibcutilsHandle();
     NativeHandle to = dupToAidl(handle);
+    EXPECT_FALSE(isAidlNativeHandleEmpty(to));
     checkEq(to, handle, true /*exceptFds*/);
     EXPECT_EQ(0, native_handle_close(handle));
     EXPECT_EQ(0, native_handle_delete(handle));
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 422b37e..524242f 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -87,7 +87,6 @@
 
 vintf_compatibility_matrix {
     name: "framework_compatibility_matrix.current.xml",
-    enabled: false,
     stem: "compatibility_matrix.current.xml",
     srcs: [
         "compatibility_matrix.current.xml",
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index d6a44d0..d19f0da 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -103,6 +103,7 @@
     framework_compatibility_matrix.5.xml \
     framework_compatibility_matrix.6.xml \
     framework_compatibility_matrix.7.xml \
+    framework_compatibility_matrix.current.xml \
     framework_compatibility_matrix.device.xml \
 
 my_framework_matrix_deps += \
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 886f7f5..d4be2bf 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -16,7 +16,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <hal format="hidl" optional="true">
         <name>android.hardware.audio.effect</name>
         <version>6.0</version>
         <version>7.0</version>
@@ -26,6 +26,26 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true">
+        <name>android.hardware.audio.core</name>
+        <version>1</version>
+        <interface>
+            <name>IModule</name>
+            <instance>default</instance>
+        </interface>
+        <interface>
+            <name>IConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.audio.effect</name>
+        <version>1</version>
+        <interface>
+            <name>IFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
          <name>android.hardware.authsecret</name>
          <version>1</version>
          <interface>
@@ -100,14 +120,6 @@
             <regex-instance>.*</regex-instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.biometrics.face</name>
-        <version>1.0</version>
-        <interface>
-            <name>IBiometricsFace</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.biometrics.face</name>
         <version>2</version>
@@ -116,14 +128,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.biometrics.fingerprint</name>
-        <version>2.1-3</version>
-        <interface>
-            <name>IBiometricsFingerprint</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.biometrics.fingerprint</name>
         <version>2</version>
@@ -148,9 +152,8 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
+    <hal format="aidl" optional="true">
         <name>android.hardware.boot</name>
-        <version>1.2</version>
         <interface>
             <name>IBootControl</name>
             <instance>default</instance>
@@ -196,9 +199,9 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
+    <hal format="aidl" optional="true">
         <name>android.hardware.confirmationui</name>
-        <version>1.0</version>
+        <version>1</version>
         <interface>
             <name>IConfirmationUI</name>
             <instance>default</instance>
@@ -238,7 +241,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <hal format="hidl" optional="true">
         <name>android.hardware.gatekeeper</name>
         <version>1.0</version>
         <interface>
@@ -246,11 +249,11 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.gnss</name>
-        <version>2.0-1</version>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.gatekeeper</name>
+        <version>1</version>
         <interface>
-            <name>IGnss</name>
+            <name>IGatekeeper</name>
             <instance>default</instance>
         </interface>
     </hal>
@@ -349,7 +352,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.identity</name>
-        <version>1-4</version>
+        <version>1-5</version>
         <interface>
             <name>IIdentityCredentialStore</name>
             <instance>default</instance>
@@ -386,23 +389,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.keymaster</name>
-        <version>3.0</version>
-        <version>4.0-1</version>
-        <interface>
-            <name>IKeymasterDevice</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.keymaster</name>
-        <version>4.0-1</version>
-        <interface>
-            <name>IKeymasterDevice</name>
-            <instance>strongbox</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.security.dice</name>
         <version>1</version>
@@ -413,7 +399,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.security.keymint</name>
-        <version>1-2</version>
+        <version>1-3</version>
         <interface>
             <name>IKeyMintDevice</name>
             <instance>default</instance>
@@ -422,7 +408,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.security.keymint</name>
-        <version>1-2</version>
+        <version>1-3</version>
         <interface>
             <name>IRemotelyProvisionedComponent</name>
             <instance>default</instance>
@@ -446,18 +432,6 @@
             <regex-instance>vendor[0-9]*_software</regex-instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.media.omx</name>
-        <version>1.0</version>
-        <interface>
-            <name>IOmx</name>
-            <instance>default</instance>
-        </interface>
-        <interface>
-            <name>IOmxStore</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.memtrack</name>
         <version>1</version>
@@ -482,14 +456,6 @@
             <regex-instance>.*</regex-instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.nfc</name>
-        <version>1.2</version>
-        <interface>
-            <name>INfc</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.nfc</name>
         <interface>
@@ -686,22 +652,28 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <hal format="aidl" optional="false">
         <name>android.hardware.thermal</name>
-        <version>2.0</version>
+        <version>1</version>
         <interface>
             <name>IThermal</name>
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
+    <hal format="aidl" optional="true">
         <name>android.hardware.tv.cec</name>
-        <version>1.0-1</version>
         <interface>
             <name>IHdmiCec</name>
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.tv.hdmi</name>
+        <interface>
+            <name>IHdmi</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.tv.input</name>
         <version>1.0</version>
@@ -726,14 +698,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.usb</name>
-        <version>1.0-3</version>
-        <interface>
-            <name>IUsb</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.usb</name>
         <interface>
@@ -781,6 +745,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1</version>
+        <interface>
+            <name>IWifi</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi</name>
         <version>1.3-6</version>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index 6de9d03..cb77c7b 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -68,6 +68,8 @@
             // does not depend on this HAL, hence it is not declared in any manifests or matrices.
             "android.hardware.fastboot@1.0",
             "android.hardware.fastboot@1.1",
+            // Fastboot AIDL
+            "android.hardware.fastboot",
 
             // Deprecated HALs.
             // HIDL
diff --git a/confirmationui/OWNERS b/confirmationui/OWNERS
new file mode 100644
index 0000000..2bcdb0e
--- /dev/null
+++ b/confirmationui/OWNERS
@@ -0,0 +1,2 @@
+swillden@google.com
+subrahmanyaman@google.com
diff --git a/confirmationui/aidl/Android.bp b/confirmationui/aidl/Android.bp
new file mode 100644
index 0000000..5395101
--- /dev/null
+++ b/confirmationui/aidl/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2022 The Android Open-Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+aidl_interface {
+    name: "android.hardware.confirmationui",
+    vendor_available: true,
+    imports: [
+        "android.hardware.security.keymint-V3",
+    ],
+    srcs: ["android/hardware/confirmationui/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            apps_enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+    },
+}
diff --git a/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationResultCallback.aidl b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationResultCallback.aidl
new file mode 100644
index 0000000..6d6ec97
--- /dev/null
+++ b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationResultCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.confirmationui;
+@VintfStability
+interface IConfirmationResultCallback {
+  void result(in int error, in byte[] formattedMessage, in byte[] confirmationToken);
+}
diff --git a/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationUI.aidl b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationUI.aidl
new file mode 100644
index 0000000..c5c7aa7
--- /dev/null
+++ b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationUI.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.confirmationui;
+@VintfStability
+interface IConfirmationUI {
+  void abort();
+  void deliverSecureInputEvent(in android.hardware.security.keymint.HardwareAuthToken secureInputToken);
+  void promptUserConfirmation(in android.hardware.confirmationui.IConfirmationResultCallback resultCB, in byte[] promptText, in byte[] extraData, in @utf8InCpp String locale, in android.hardware.confirmationui.UIOption[] uiOptions);
+  const int OK = 0;
+  const int CANCELED = 1;
+  const int ABORTED = 2;
+  const int OPERATION_PENDING = 3;
+  const int IGNORED = 4;
+  const int SYSTEM_ERROR = 5;
+  const int UNIMPLEMENTED = 6;
+  const int UNEXPECTED = 7;
+  const int UI_ERROR = 65536;
+  const int UI_ERROR_MISSING_GLYPH = 65537;
+  const int UI_ERROR_MESSAGE_TOO_LONG = 65538;
+  const int UI_ERROR_MALFORMED_UTF8ENCODING = 65539;
+  const int TEST_KEY_BYTE = 165;
+  const int MAX_MESSAGE_SIZE = 6144;
+}
diff --git a/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/TestModeCommands.aidl b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/TestModeCommands.aidl
new file mode 100644
index 0000000..b8629d1
--- /dev/null
+++ b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/TestModeCommands.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.confirmationui;
+@Backing(type="int") @VintfStability
+enum TestModeCommands {
+  OK_EVENT = 0,
+  CANCEL_EVENT = 1,
+}
diff --git a/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/UIOption.aidl b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/UIOption.aidl
new file mode 100644
index 0000000..ebecf9e
--- /dev/null
+++ b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/UIOption.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.confirmationui;
+@Backing(type="int") @VintfStability
+enum UIOption {
+  ACCESSIBILITY_INVERTED = 0,
+  ACCESSIBILITY_MAGNIFIED = 1,
+}
diff --git a/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl
new file mode 100644
index 0000000..2165fdd
--- /dev/null
+++ b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl
@@ -0,0 +1,66 @@
+/*
+ * 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.confirmationui;
+
+import android.hardware.confirmationui.IConfirmationUI;
+
+/**
+ * Callback interface passed to IConfirmationUI::promptUserConfirmation().
+ * Informs the caller about the result of the prompt operation.
+ */
+@VintfStability
+interface IConfirmationResultCallback {
+    /**
+     * This callback is called by the confirmation provider when it stops prompting the user.
+     * Iff the user has confirmed the prompted text, error is ErrorCode::OK and the
+     * parameters formattedMessage and confirmationToken hold the values needed to request
+     * a signature from keymaster.
+     * In all other cases formattedMessage and confirmationToken must be of length 0.
+     *
+     * @param error - OK: IFF the user has confirmed the prompt.
+     *              - CANCELED: If the user has pressed the cancel button.
+     *              - ABORTED: If IConfirmationUI::abort() was called.
+     *              - SYSTEM_ERROR: If an unexpected System error occurred that prevented the TUI
+     *                             from being shut down gracefully.
+     *
+     * @param formattedMessage holds the prompt text and extra data.
+     *                         The message is CBOR (RFC 7049) encoded and has the following format:
+     *                         CBOR_MAP{ "prompt", <promptText>, "extra", <extraData> }
+     *                         The message is a CBOR encoded map (type 5) with the keys
+     *                         "prompt" and "extra". The keys are encoded as CBOR text string
+     *                         (type 3). The value <promptText> is encoded as CBOR text string
+     *                         (type 3), and the value <extraData> is encoded as CBOR byte string
+     *                         (type 2). The map must have exactly one key value pair for each of
+     *                         the keys "prompt" and "extra". Other keys are not allowed.
+     *                         The value of "prompt" is given by the proptText argument to
+     *                         IConfirmationUI::promptUserConfirmation and must not be modified
+     *                         by the implementation.
+     *                         The value of "extra" is given by the extraData argument to
+     *                         IConfirmationUI::promptUserConfirmation and must not be modified
+     *                         or interpreted by the implementation.
+     *
+     * @param confirmationToken a 32-byte HMAC-SHA256 value, computed over
+     *                          "confirmation token" || <formattedMessage>
+     *                          i.e. the literal UTF-8 encoded string "confirmation token", without
+     *                          the "", concatenated with the formatted message as returned in the
+     *                          formattedMessage argument. The HMAC is keyed with a 256-bit secret
+     *                          which is shared with Keymaster. In test mode the test key MUST be
+     *                          used (see types.hal TestModeCommands and
+     * IConfirmationUI::TEST_KEY_BYTE).
+     */
+    void result(in int error, in byte[] formattedMessage, in byte[] confirmationToken);
+}
diff --git a/confirmationui/aidl/android/hardware/confirmationui/IConfirmationUI.aidl b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationUI.aidl
new file mode 100644
index 0000000..f071126
--- /dev/null
+++ b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationUI.aidl
@@ -0,0 +1,146 @@
+/*
+ * 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.confirmationui;
+
+import android.hardware.confirmationui.IConfirmationResultCallback;
+import android.hardware.confirmationui.UIOption;
+import android.hardware.security.keymint.HardwareAuthToken;
+
+@VintfStability
+interface IConfirmationUI {
+    // Possible Errors.
+    /**
+     * API call succeeded or the user gave approval (result callback).
+     */
+    const int OK = 0;
+    /**
+     * The user canceled the TUI (result callback).
+     */
+    const int CANCELED = 1;
+    /**
+     * IConfirmationUI::abort() was called. (result callback).
+     */
+    const int ABORTED = 2;
+    /**
+     * Cannot start another prompt.
+     */
+    const int OPERATION_PENDING = 3;
+    /**
+     * IConfirmationUI::deliverSecureInputEvent call was ignored.
+     */
+    const int IGNORED = 4;
+    /**
+     * An unexpected system error occurred.
+     */
+    const int SYSTEM_ERROR = 5;
+    /**
+     * Returned by an unimplemented API call.
+     */
+    const int UNIMPLEMENTED = 6;
+    /**
+     * This is returned when an error is diagnosed that should have been
+     * caught by earlier input sanitization. Should never be seen in production.
+     */
+    const int UNEXPECTED = 7;
+    /**
+     * General UI error.
+     */
+    const int UI_ERROR = 0x10000;
+    /**
+     * This is returned if there is no corresponding glyph for a character.
+     */
+    const int UI_ERROR_MISSING_GLYPH = 0x10001;
+    /**
+     * The implementation must return this error code on promptUserConfirmation if the
+     * resulting formatted message does not fit into MAX_MESSAGE_SIZE bytes. It is
+     * advised that the implementation formats the message upon receiving this API call to
+     * be able to diagnose this syndrome.
+     */
+    const int UI_ERROR_MESSAGE_TOO_LONG = 0x10002;
+    /**
+     * This is returned if the UTF8 encoding is malformed.
+     */
+    const int UI_ERROR_MALFORMED_UTF8ENCODING = 0x10003;
+
+    // Constants
+    /**
+     * The test key is 32byte word with all bytes set to TEST_KEY_BYTE.
+     */
+    const int TEST_KEY_BYTE = 0xA5;
+    /**
+     * This defines the maximum message size. This indirectly limits the size of the prompt text
+     * and the extra data that can be passed to the confirmation UI. The prompt text and extra data
+     * must fit in to this size including CBOR header information.
+     */
+    const int MAX_MESSAGE_SIZE = 0x1800;
+
+    /**
+     * Aborts a pending user prompt. This allows the framework to gracefully end a TUI dialog.
+     * If a TUI operation was pending the corresponding call back is informed with
+     * ErrorCode::Aborted.
+     */
+    void abort();
+
+    /**
+     * DeliverSecureInput is used by the framework to deliver a secure input event to the
+     * confirmation provider.
+     *
+     * VTS test mode:
+     * This function can be used to test certain code paths non-interactively.
+     * See TestModeCommands.aidl for details.
+     *
+     * @param secureInputToken An authentication token as generated by Android authentication
+     *                         providers.
+     */
+    void deliverSecureInputEvent(in HardwareAuthToken secureInputToken);
+
+    /**
+     * Asynchronously initiates a confirmation UI dialog prompting the user to confirm a given text.
+     * The TUI prompt must be implemented in such a way that a positive response indicates with
+     * high confidence that a user has seen the given prompt text even if the Android framework
+     * including the kernel was compromised.
+     *
+     * Service status return:
+     *
+     * OK IFF the dialog was successfully started. In this case, and only in this
+     *                      case, the implementation must, eventually, call the callback to
+     *                      indicate completion.
+     * OPERATION_PENDING is returned when the confirmation provider is currently
+     *                      in use.
+     * SYSTEM_ERROR an error occurred trying to communicate with the confirmation
+     *                      provider (e.g. trusted app).
+     * UI_ERROR the confirmation provider encountered an issue with displaying
+     *                      the prompt text to the user.
+     *
+     * @param resultCB Implementation of IResultCallback. Used by the implementation to report
+     *                 the result of the current pending user prompt.
+     *
+     * @param promptText UTF-8 encoded bytes which is to be presented to the user.
+     *
+     * @param extraData A binary blob that must be included in the formatted output message as is.
+     *                  It is opaque to the implementation. Implementations must neither interpret
+     *                  nor modify the content.
+     *
+     * @param locale String specifying the locale that must be used by the TUI dialog. The string
+     *                      is an IETF BCP 47 tag.
+     *
+     * @param uiOptions A set of uiOptions manipulating how the confirmation prompt is displayed.
+     *                  Refer to UIOption in types.hal for possible options.
+     */
+    void promptUserConfirmation(in IConfirmationResultCallback resultCB, in byte[] promptText,
+            in byte[] extraData, in @utf8InCpp String locale, in UIOption[] uiOptions);
+}
diff --git a/confirmationui/aidl/android/hardware/confirmationui/TestModeCommands.aidl b/confirmationui/aidl/android/hardware/confirmationui/TestModeCommands.aidl
new file mode 100644
index 0000000..5b1d8fb
--- /dev/null
+++ b/confirmationui/aidl/android/hardware/confirmationui/TestModeCommands.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.confirmationui;
+
+/**
+ * Test mode commands.
+ *
+ * IConfirmationUI::deliverSecureInputEvent can be used to test certain code paths.
+ * To that end, the caller passes an auth token that has an HMAC keyed with the test key
+ * (see IConfirmationUI::TEST_KEY_BYTE). Implementations first check the HMAC against test key.
+ * If the test key produces a matching HMAC, the implementation evaluates the challenge field
+ * of the auth token against the values defined in TestModeCommand.
+ * If the command indicates that a confirmation token is to be generated the test key MUST be used
+ * to generate this confirmation token.
+ *
+ * See command code for individual test command descriptions.
+ */
+@VintfStability
+@Backing(type="int")
+enum TestModeCommands {
+    /**
+     * Simulates the user pressing the OK button on the UI. If no operation is pending
+     * ResponseCode::Ignored must be returned. A pending operation is finalized successfully
+     * see IConfirmationResultCallback::result, however, the test key
+     * (see IConfirmationUI::TEST_KEY_BYTE) MUST be used to generate the confirmation token.
+     */
+    OK_EVENT = 0,
+    /**
+     * Simulates the user pressing the CANCEL button on the UI. If no operation is pending
+     * Result::Ignored must be returned. A pending operation is finalized as specified in
+     * IConfirmationResultCallback.hal.
+     */
+    CANCEL_EVENT = 1,
+}
diff --git a/confirmationui/aidl/android/hardware/confirmationui/UIOption.aidl b/confirmationui/aidl/android/hardware/confirmationui/UIOption.aidl
new file mode 100644
index 0000000..b242c53
--- /dev/null
+++ b/confirmationui/aidl/android/hardware/confirmationui/UIOption.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.confirmationui;
+
+/**
+ * UI modification options.
+ */
+@VintfStability
+@Backing(type="int")
+enum UIOption {
+    /**
+     * Accessibility: Requests color inverted style.
+     */
+    ACCESSIBILITY_INVERTED = 0,
+    /**
+     * Accessibility: Requests magnified style.
+     */
+    ACCESSIBILITY_MAGNIFIED = 1,
+}
diff --git a/confirmationui/aidl/vts/functional/Android.bp b/confirmationui/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..3649c87
--- /dev/null
+++ b/confirmationui/aidl/vts/functional/Android.bp
@@ -0,0 +1,45 @@
+//
+// 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
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsHalConfirmationUITargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "keymint_use_latest_hal_aidl_ndk_shared",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsHalConfirmationUITargetTest.cpp",
+    ],
+    static_libs: [
+        "android.hardware.confirmationui-V1-ndk",
+        "libcn-cbor",
+        "android.hardware.confirmationui-support-lib",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libcrypto",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp b/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp
new file mode 100644
index 0000000..61dae8b
--- /dev/null
+++ b/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp
@@ -0,0 +1,535 @@
+/*
+ * 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 "ConfirmationIOAidlHalTest"
+
+#include <algorithm>
+#include <condition_variable>
+#include <future>
+#include <iostream>
+#include <memory>
+#include <mutex>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/confirmationui/BnConfirmationResultCallback.h>
+#include <aidl/android/hardware/confirmationui/IConfirmationUI.h>
+#include <aidl/android/hardware/confirmationui/TestModeCommands.h>
+#include <aidl/android/hardware/confirmationui/UIOption.h>
+#include <android-base/thread_annotations.h>
+#include <android/hardware/confirmationui/support/confirmationui_utils.h>
+#include <cutils/log.h>
+
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+
+#include <cn-cbor/cn-cbor.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_status.h>
+
+static constexpr int TIMEOUT_PERIOD = 10;
+
+namespace aidl::android::hardware::confirmationui::test {
+using ::aidl::android::hardware::security::keymint::HardwareAuthenticatorType;
+using ::aidl::android::hardware::security::keymint::HardwareAuthToken;
+using ::android::hardware::confirmationui::support::auth_token_key_t;
+using ::android::hardware::confirmationui::support::ByteBufferProxy;
+using ::android::hardware::confirmationui::support::HMac;
+using ::android::hardware::confirmationui::support::hmac_t;
+using ::android::hardware::confirmationui::support::hton;
+using ::android::hardware::confirmationui::support::NullOr;
+using std::shared_ptr;
+using std::string;
+using std::vector;
+
+namespace {
+const auth_token_key_t testKey(static_cast<uint8_t>(IConfirmationUI::TEST_KEY_BYTE));
+
+class HMacImplementation {
+  public:
+    static NullOr<hmac_t> hmac256(const auth_token_key_t& key,
+                                  std::initializer_list<ByteBufferProxy> buffers) {
+        HMAC_CTX hmacCtx;
+        HMAC_CTX_init(&hmacCtx);
+        if (!HMAC_Init_ex(&hmacCtx, key.data(), key.size(), EVP_sha256(), nullptr)) {
+            return {};
+        }
+        for (auto& buffer : buffers) {
+            if (!HMAC_Update(&hmacCtx, buffer.data(), buffer.size())) {
+                return {};
+            }
+        }
+        hmac_t result;
+        if (!HMAC_Final(&hmacCtx, result.data(), nullptr)) {
+            return {};
+        }
+        return result;
+    }
+};
+
+using HMacer = HMac<HMacImplementation>;
+
+template <typename... Data>
+vector<uint8_t> testHMAC(const Data&... data) {
+    auto hmac = HMacer::hmac256(testKey, data...);
+    if (!hmac.isOk()) {
+        ADD_FAILURE() << "Failed to compute test hmac.  This is a self-test error.";
+        return {};
+    }
+    vector<uint8_t> result(hmac.value().size());
+    std::copy(hmac.value().data(), hmac.value().data() + hmac.value().size(), result.data());
+    return result;
+}
+
+template <typename T>
+auto toBytes(const T& v) -> const uint8_t (&)[sizeof(T)] {
+    return *reinterpret_cast<const uint8_t(*)[sizeof(T)]>(&v);
+}
+
+HardwareAuthToken makeTestToken(const TestModeCommands command, uint64_t timestamp = 0) {
+    HardwareAuthToken auth_token;
+    auth_token.challenge = static_cast<uint64_t>(command);
+    auth_token.userId = 0;
+    auth_token.authenticatorId = 0;
+    auth_token.authenticatorType = HardwareAuthenticatorType::NONE;
+    auth_token.timestamp = {static_cast<int64_t>(timestamp)};
+
+    // Canonical form  of auth-token v0
+    // version (1 byte)
+    // challenge (8 bytes)
+    // user_id (8 bytes)
+    // authenticator_id (8 bytes)
+    // authenticator_type (4 bytes)
+    // timestamp (8 bytes)
+    // total 37 bytes
+    auth_token.mac = testHMAC("\0",
+                              toBytes(auth_token.challenge),                //
+                              toBytes(auth_token.userId),                   //
+                              toBytes(auth_token.authenticatorId),          //
+                              toBytes(hton(auth_token.authenticatorType)),  //
+                              toBytes(hton(auth_token.timestamp)));         //
+
+    return auth_token;
+}
+
+#define DEBUG_CONFRIMATIONUI_UTILS_TEST
+
+#ifdef DEBUG_CONFRIMATIONUI_UTILS_TEST
+std::ostream& hexdump(std::ostream& out, const uint8_t* data, size_t size) {
+    for (size_t i = 0; i < size; ++i) {
+        uint8_t byte = data[i];
+        out << std::hex << std::setw(2) << std::setfill('0') << (unsigned)byte;
+        switch (i & 0xf) {
+            case 0xf:
+                out << "\n";
+                break;
+            case 7:
+                out << "  ";
+                break;
+            default:
+                out << " ";
+                break;
+        }
+    }
+    return out;
+}
+#endif
+
+constexpr char hex_value[256] = {0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 1,  2,  3,  4,  5,  6,  7, 8, 9, 0, 0, 0, 0, 0, 0,  // '0'..'9'
+                                 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 'A'..'F'
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 'a'..'f'
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+std::string hex2str(std::string a) {
+    std::string b;
+    size_t num = a.size() / 2;
+    b.resize(num);
+    for (size_t i = 0; i < num; i++) {
+        b[i] = (hex_value[a[i * 2] & 0xFF] << 4) + (hex_value[a[i * 2 + 1] & 0xFF]);
+    }
+    return b;
+}
+
+int getReturnCode(const ::ndk::ScopedAStatus& result) {
+    if (result.isOk()) return IConfirmationUI::OK;
+
+    if (result.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+        return static_cast<int>(result.getServiceSpecificError());
+    }
+    return result.getStatus();
+}
+
+}  // namespace
+
+class ConfirmationUIAidlTest : public ::testing::TestWithParam<std::string> {
+  public:
+    void TearDown() override { confirmator_->abort(); }
+    void SetUp() override {
+        std::string name = GetParam();
+        ASSERT_TRUE(AServiceManager_isDeclared(name.c_str())) << name;
+        ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
+        ASSERT_NE(binder, nullptr);
+        confirmator_ = IConfirmationUI::fromBinder(binder);
+        ASSERT_NE(confirmator_, nullptr);
+    }
+
+    // Used as a mechanism to inform the test about data/event callback
+    inline void notify() {
+        std::unique_lock<std::mutex> lock(mtx_);
+        cv_.notify_one();
+    }
+
+    // Test code calls this function to wait for data/event callback
+    inline std::cv_status wait() {
+        std::unique_lock<std::mutex> lock(mtx_);
+        auto now = std::chrono::system_clock::now();
+        std::cv_status status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+        return status;
+    }
+
+  protected:
+    shared_ptr<IConfirmationUI> confirmator_;
+
+  private:
+    // synchronization objects
+    std::mutex mtx_;
+    std::condition_variable cv_;
+};
+
+class ConfirmationTestCallback
+    : public ::aidl::android::hardware::confirmationui::BnConfirmationResultCallback {
+  public:
+    ConfirmationTestCallback(ConfirmationUIAidlTest& parent) : parent_(parent){};
+    virtual ~ConfirmationTestCallback() = default;
+
+    ::ndk::ScopedAStatus result(int32_t err, const vector<uint8_t>& msg,
+                                const vector<uint8_t>& confToken) override {
+        error_ = err;
+        formattedMessage_ = msg;
+        confirmationToken_ = confToken;
+        parent_.notify();
+        return ndk::ScopedAStatus::ok();
+    }
+
+    bool verifyConfirmationToken() {
+        static constexpr char confirmationPrefix[] = "confirmation token";
+        EXPECT_EQ(32U, confirmationToken_.size());
+        return 32U == confirmationToken_.size() &&
+               !memcmp(confirmationToken_.data(),
+                       testHMAC(confirmationPrefix, formattedMessage_).data(), 32);
+    }
+
+    int error_;
+    vector<uint8_t> formattedMessage_;
+    vector<uint8_t> confirmationToken_;
+
+  private:
+    ConfirmationUIAidlTest& parent_;
+};
+
+struct CnCborDeleter {
+    void operator()(cn_cbor* ptr) { cn_cbor_free(ptr); }
+};
+
+typedef std::unique_ptr<cn_cbor, CnCborDeleter> CnCborPtr;
+
+// Simulates the User taping Ok
+TEST_P(ConfirmationUIAidlTest, UserOkTest) {
+    static constexpr char test_prompt[] = "Me first, gimme gimme!";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    shared_ptr<ConfirmationTestCallback> conf_cb =
+            ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+    vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+    vector<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+    // Simulate the user taping ok.
+    ASSERT_TRUE(confirmator_->deliverSecureInputEvent(makeTestToken(TestModeCommands::OK_EVENT))
+                        .isOk());
+    // Wait for the callback.
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    ASSERT_EQ(IConfirmationUI::OK, conf_cb->error_);
+
+    ASSERT_TRUE(conf_cb->verifyConfirmationToken());
+
+    cn_cbor_errback cn_cbor_error;
+    auto parsed_message = CnCborPtr(cn_cbor_decode(
+            conf_cb->formattedMessage_.data(), conf_cb->formattedMessage_.size(), &cn_cbor_error));
+    // is parsable CBOR
+    ASSERT_TRUE(parsed_message.get());
+    // is a map
+    ASSERT_EQ(CN_CBOR_MAP, parsed_message->type);
+
+    // the message must have exactly 2 key value pairs.
+    // cn_cbor holds 2*<no_of_pairs> in the length field
+    ASSERT_EQ(4, parsed_message->length);
+    // map has key "prompt"
+    auto prompt = cn_cbor_mapget_string(parsed_message.get(), "prompt");
+    ASSERT_TRUE(prompt);
+    ASSERT_EQ(CN_CBOR_TEXT, prompt->type);
+    ASSERT_EQ(22, prompt->length);
+    ASSERT_EQ(0, memcmp(test_prompt, prompt->v.str, 22));
+    // map has key "extra"
+    auto extra_out = cn_cbor_mapget_string(parsed_message.get(), "extra");
+    ASSERT_TRUE(extra_out);
+    ASSERT_EQ(CN_CBOR_BYTES, extra_out->type);
+    ASSERT_EQ(3, extra_out->length);
+    ASSERT_EQ(0, memcmp(test_extra, extra_out->v.bytes, 3));
+}
+
+// Initiates a confirmation prompt with a message that is too long
+TEST_P(ConfirmationUIAidlTest, MessageTooLongTest) {
+    static constexpr uint8_t test_extra[IConfirmationUI::MAX_MESSAGE_SIZE] = {};
+    static constexpr char test_prompt[] = "D\'oh!";
+    shared_ptr<ConfirmationTestCallback> conf_cb =
+            ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+    vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+    vector<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
+    auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
+    ASSERT_EQ(IConfirmationUI::UI_ERROR_MESSAGE_TOO_LONG, getReturnCode(result));
+}
+
+// If the message gets very long some HAL implementations might fail even before the message
+// reaches the trusted app implementation. But the HAL must still diagnose the correct error.
+TEST_P(ConfirmationUIAidlTest, MessageWayTooLongTest) {
+    static constexpr uint8_t test_extra[(IConfirmationUI::MAX_MESSAGE_SIZE)*10] = {};
+    static constexpr char test_prompt[] = "D\'oh!";
+    shared_ptr<ConfirmationTestCallback> conf_cb =
+            ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+    vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+    vector<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
+    auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
+    ASSERT_EQ(IConfirmationUI::UI_ERROR_MESSAGE_TOO_LONG, getReturnCode(result));
+}
+
+// Simulates the User tapping the Cancel
+TEST_P(ConfirmationUIAidlTest, UserCancelTest) {
+    static constexpr char test_prompt[] = "Me first, gimme gimme!";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    shared_ptr<ConfirmationTestCallback> conf_cb =
+            ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+    vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+    vector<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+
+    // Simulate the user taping ok.
+    ASSERT_TRUE(confirmator_->deliverSecureInputEvent(makeTestToken(TestModeCommands::CANCEL_EVENT))
+                        .isOk());
+    // Wait for the callback.
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    ASSERT_EQ(IConfirmationUI::CANCELED, conf_cb->error_);
+
+    ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+    ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Simulates the framework cancelling an ongoing prompt
+TEST_P(ConfirmationUIAidlTest, AbortTest) {
+    static constexpr char test_prompt[] = "Me first, gimme gimme!";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    shared_ptr<ConfirmationTestCallback> conf_cb =
+            ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+    vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+    vector<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+
+    confirmator_->abort();
+
+    // Wait for the callback.
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+    ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+    ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
+// the design guidelines.
+TEST_P(ConfirmationUIAidlTest, PortableMessageTest1) {
+    static constexpr char test_prompt[] =
+            "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
+            "WWWWWWWWWWWWWW";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    shared_ptr<ConfirmationTestCallback> conf_cb =
+            ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+    vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+    vector<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+
+    confirmator_->abort();
+
+    // Wait for the callback.
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+    ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+    ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
+// the design guidelines in magnified mode.
+TEST_P(ConfirmationUIAidlTest, PortableMessageTest1Magnified) {
+    static constexpr char test_prompt[] =
+            "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
+            "WWWWWWWWWWWWWW";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    shared_ptr<ConfirmationTestCallback> conf_cb =
+            ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+    vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+    vector<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_TRUE(confirmator_
+                        ->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+                                                 {UIOption::ACCESSIBILITY_MAGNIFIED})
+                        .isOk());
+
+    confirmator_->abort();
+
+    // Wait for the callback.
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+    ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+    ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
+// required by the design guidelines.
+TEST_P(ConfirmationUIAidlTest, PortableMessageTest2) {
+    static constexpr char test_prompt[] =
+            "WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
+            "WWWWWWWWWWWW WWWWWWWWWWWW";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    shared_ptr<ConfirmationTestCallback> conf_cb =
+            ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+    vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+    vector<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+
+    confirmator_->abort();
+
+    // Wait for the callback.
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+    ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+    ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
+// required by the design guidelines in magnified mode.
+TEST_P(ConfirmationUIAidlTest, PortableMessageTest2Magnified) {
+    static constexpr char test_prompt[] =
+            "WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
+            "WWWWWWWWWWWW WWWWWWWWWWWW";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    shared_ptr<ConfirmationTestCallback> conf_cb =
+            ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+    vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+    vector<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_TRUE(confirmator_
+                        ->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+                                                 {UIOption::ACCESSIBILITY_MAGNIFIED})
+                        .isOk());
+
+    confirmator_->abort();
+
+    // Wait for the callback.
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+    ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+    ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Passing malformed UTF-8 to the confirmation UI
+// This test passes a string that ends in the middle of a multibyte character
+TEST_P(ConfirmationUIAidlTest, MalformedUTF8Test1) {
+    static constexpr char test_prompt[] = {char(0xc0), 0};
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    shared_ptr<ConfirmationTestCallback> conf_cb =
+            ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+    vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+    vector<uint8_t> extra(test_extra, test_extra + 3);
+    auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
+    ASSERT_EQ(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING, getReturnCode(result));
+}
+
+// Passing malformed UTF-8 to the confirmation UI
+// This test passes a string with a 5-byte character.
+TEST_P(ConfirmationUIAidlTest, MalformedUTF8Test2) {
+    static constexpr char test_prompt[] = {char(0xf8), char(0x82), char(0x82),
+                                           char(0x82), char(0x82), 0};
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    shared_ptr<ConfirmationTestCallback> conf_cb =
+            ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+    vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+    vector<uint8_t> extra(test_extra, test_extra + 3);
+    auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
+    ASSERT_EQ(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING, getReturnCode(result));
+}
+
+// Passing malformed UTF-8 to the confirmation UI
+// This test passes a string with a 2-byte character followed by a stray non UTF-8 character.
+TEST_P(ConfirmationUIAidlTest, MalformedUTF8Test3) {
+    static constexpr char test_prompt[] = {char(0xc0), char(0x82), char(0x83), 0};
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    shared_ptr<ConfirmationTestCallback> conf_cb =
+            ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+    vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+    vector<uint8_t> extra(test_extra, test_extra + 3);
+    auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
+    ASSERT_EQ(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING, getReturnCode(result));
+}
+
+// Test the implementation of HMAC SHA 256 against a golden blob.
+TEST(ConfirmationUITestSelfTest, HMAC256SelfTest) {
+    const char key_str[32] = "keykeykeykeykeykeykeykeykeykeyk";
+    const uint8_t(&key)[32] = *reinterpret_cast<const uint8_t(*)[32]>(key_str);
+    auto expected = hex2str("2377fbcaa7fb3f6c20cfa1d9ebc60e9922cf58c909e25e300f3cb57f7805c886");
+    auto result = HMacer::hmac256(key, "value1", "value2", "value3");
+
+#ifdef DEBUG_CONFRIMATIONUI_UTILS_TEST
+    hexdump(std::cout, reinterpret_cast<const uint8_t*>(expected.data()), 32) << std::endl;
+    hexdump(std::cout, result.value().data(), 32) << std::endl;
+#endif
+
+    ByteBufferProxy expected_bytes(expected);
+    ASSERT_TRUE(result.isOk());
+    ASSERT_EQ(expected, result.value());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ConfirmationUIAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, ConfirmationUIAidlTest,
+        testing::ValuesIn(::android::getAidlHalInstanceNames(IConfirmationUI::descriptor)),
+        ::android::PrintInstanceNameToString);
+
+}  // namespace aidl::android::hardware::confirmationui::test
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/confirmationui/support/Android.bp b/confirmationui/support/Android.bp
index 6ab83f2..1200115 100644
--- a/confirmationui/support/Android.bp
+++ b/confirmationui/support/Android.bp
@@ -36,7 +36,7 @@
     ],
     export_include_dirs: [
         "include",
-    ]
+    ],
 }
 
 cc_test {
@@ -56,6 +56,5 @@
         "libhidlbase",
     ],
     test_suites: ["general-tests"],
-    clang: true,
-    cflags: [ "-O0" ],
+    cflags: ["-O0"],
 }
diff --git a/drm/aidl/Android.bp b/drm/aidl/Android.bp
index 0fdba31..6273a38 100644
--- a/drm/aidl/Android.bp
+++ b/drm/aidl/Android.bp
@@ -23,9 +23,6 @@
             sdk_version: "module_current",
         },
         ndk: {
-            vndk: {
-                enabled: true,
-            },
             min_sdk_version: "current",
         },
     },
diff --git a/dumpstate/aidl/Android.bp b/dumpstate/aidl/Android.bp
index b250d74..1eb8b32 100644
--- a/dumpstate/aidl/Android.bp
+++ b/dumpstate/aidl/Android.bp
@@ -34,11 +34,6 @@
             enabled: true,
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/fastboot/OWNERS b/fastboot/OWNERS
new file mode 100644
index 0000000..286b65f
--- /dev/null
+++ b/fastboot/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 1228891
+dvander@google.com
+elsk@google.com
+dhavale@google.com
diff --git a/fastboot/aidl/Android.bp b/fastboot/aidl/Android.bp
new file mode 100644
index 0000000..a5735ab
--- /dev/null
+++ b/fastboot/aidl/Android.bp
@@ -0,0 +1,38 @@
+// 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.fastboot",
+    vendor_available: true,
+    recovery_available: true,
+    srcs: ["android/hardware/fastboot/*.aidl"],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            enabled: false,
+        },
+    },
+}
diff --git a/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/FileSystemType.aidl b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/FileSystemType.aidl
new file mode 100644
index 0000000..b15d037
--- /dev/null
+++ b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/FileSystemType.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.fastboot;
+@Backing(type="byte") @VintfStability
+enum FileSystemType {
+  EXT4 = 0,
+  F2FS = 1,
+  RAW = 2,
+}
diff --git a/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/IFastboot.aidl b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/IFastboot.aidl
new file mode 100644
index 0000000..445fcde
--- /dev/null
+++ b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/IFastboot.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.fastboot;
+@VintfStability
+interface IFastboot {
+  String doOemCommand(in String oemCmd);
+  void doOemSpecificErase();
+  int getBatteryVoltageFlashingThreshold();
+  boolean getOffModeChargeState();
+  android.hardware.fastboot.FileSystemType getPartitionType(in String partitionName);
+  String getVariant();
+  const int FAILURE_UNKNOWN = 1;
+}
diff --git a/fastboot/aidl/android/hardware/fastboot/FileSystemType.aidl b/fastboot/aidl/android/hardware/fastboot/FileSystemType.aidl
new file mode 100644
index 0000000..b4027ec
--- /dev/null
+++ b/fastboot/aidl/android/hardware/fastboot/FileSystemType.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.fastboot;
+
+@VintfStability
+@Backing(type="byte")
+enum FileSystemType {
+    /**
+     * Fourth extended file system.
+     */
+    EXT4,
+    /**
+     * Flash Friendly File System.
+     */
+    F2FS,
+    /**
+     * Raw file system.
+     */
+    RAW,
+}
diff --git a/fastboot/aidl/android/hardware/fastboot/IFastboot.aidl b/fastboot/aidl/android/hardware/fastboot/IFastboot.aidl
new file mode 100644
index 0000000..abdc215
--- /dev/null
+++ b/fastboot/aidl/android/hardware/fastboot/IFastboot.aidl
@@ -0,0 +1,94 @@
+/*
+ * 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.fastboot;
+
+import android.hardware.fastboot.FileSystemType;
+
+/**
+ * IFastboot interface implements vendor specific fastboot commands.
+ */
+@VintfStability
+interface IFastboot {
+    /**
+     * Status code for function.
+     * Operation failed due to unknown reason.
+     */
+    const int FAILURE_UNKNOWN = 1;
+    /**
+     * Executes a fastboot OEM command.
+     *
+     * @param oemCmd The oem command that is passed to the fastboot HAL.
+     * @return optional String if the operation is successful and output is expected
+     *         for the command.
+     * @throws :
+     *         - EX_ILLEGAL_ARGUMENT for bad arguments.
+     *         - EX_UNSUPPORTED_OPERATION for unsupported commands.
+     *         - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN for other errors.
+     */
+    String doOemCommand(in String oemCmd);
+
+    /**
+     * Executes an OEM specific erase after fastboot erase userdata.
+     *
+     * @throws :
+     *         - EX_UNSUPPORTED_OPERATION if it is not supported.
+     *         - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN for
+     *           unknown error in oem specific command or other errors.
+     */
+    void doOemSpecificErase();
+
+    /**
+     * Returns the minimum battery voltage required for flashing in mV.
+     *
+     * @return Minimum batterery voltage (in mV) required for flashing to
+     *         be successful.
+     * @throws :
+     *         - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN if error.
+     */
+    int getBatteryVoltageFlashingThreshold();
+
+    /**
+     * Returns whether off-mode-charging is enabled. If enabled, the device
+     *      autoboots into a special mode when power is applied.
+     *
+     * @return Returns whether off-mode-charging is enabled.
+     * @throws :
+     *         - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN if error.
+     */
+    boolean getOffModeChargeState();
+
+    /**
+     * Returns the file system type of the partition. Implementation is only
+     *       required for physical partitions that need to be wiped and reformatted.
+     * @param in partitionName Name of the partition.
+     * @return Returns the file system type of the partition. Type can be ext4,
+     *         f2fs or raw.
+     * @throws :
+     *         - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN if the partition
+     *           is invalid or does not require reformatting.
+     */
+    FileSystemType getPartitionType(in String partitionName);
+
+    /**
+     * Returns an OEM-defined string indicating the variant of the device, for
+     * example, US and ROW.
+     * @return Indicates the device variant.
+     * @throws :
+     *         - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN if error.
+     */
+    String getVariant();
+}
diff --git a/fastboot/aidl/default/Android.bp b/fastboot/aidl/default/Android.bp
new file mode 100644
index 0000000..5cd4542
--- /dev/null
+++ b/fastboot/aidl/default/Android.bp
@@ -0,0 +1,39 @@
+//
+// 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 {
+    name: "android.hardware.fastboot-impl-mock",
+    recovery: true,
+    srcs: [
+        "Fastboot.cpp",
+    ],
+    relative_install_path: "hw",
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libutils",
+        "libcutils",
+        "android.hardware.fastboot-V1-ndk",
+    ],
+}
diff --git a/fastboot/aidl/default/Fastboot.cpp b/fastboot/aidl/default/Fastboot.cpp
new file mode 100644
index 0000000..1ba73d3
--- /dev/null
+++ b/fastboot/aidl/default/Fastboot.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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 "Fastboot.h"
+
+using ndk::ScopedAStatus;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace fastboot {
+
+ScopedAStatus Fastboot::getPartitionType(const std::string& in_partitionName,
+                                         FileSystemType* _aidl_return) {
+    if (in_partitionName.empty()) {
+        return ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                           "Invalid partition name");
+    }
+    *_aidl_return = FileSystemType::RAW;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Fastboot::doOemCommand(const std::string& in_oemCmd, std::string* _aidl_return) {
+    *_aidl_return = "";
+    if (in_oemCmd.empty()) {
+        return ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, "Invalid command");
+    }
+    return ScopedAStatus::fromExceptionCodeWithMessage(
+            EX_UNSUPPORTED_OPERATION, "Command not supported in default implementation");
+}
+
+ScopedAStatus Fastboot::getVariant(std::string* _aidl_return) {
+    *_aidl_return = "NA";
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Fastboot::getOffModeChargeState(bool* _aidl_return) {
+    *_aidl_return = false;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Fastboot::getBatteryVoltageFlashingThreshold(int32_t* _aidl_return) {
+    *_aidl_return = 0;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Fastboot::doOemSpecificErase() {
+    return ScopedAStatus::fromExceptionCodeWithMessage(
+            EX_UNSUPPORTED_OPERATION, "Command not supported in default implementation");
+}
+
+}  // namespace fastboot
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/fastboot/aidl/default/Fastboot.h b/fastboot/aidl/default/Fastboot.h
new file mode 100644
index 0000000..48e2c38
--- /dev/null
+++ b/fastboot/aidl/default/Fastboot.h
@@ -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.
+ */
+
+#pragma once
+
+#include "aidl/android/hardware/fastboot/BnFastboot.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace fastboot {
+class Fastboot : public BnFastboot {
+    ::ndk::ScopedAStatus doOemCommand(const std::string& in_oemCmd,
+                                      std::string* _aidl_return) override;
+    ::ndk::ScopedAStatus doOemSpecificErase() override;
+    ::ndk::ScopedAStatus getBatteryVoltageFlashingThreshold(int32_t* _aidl_return) override;
+    ::ndk::ScopedAStatus getOffModeChargeState(bool* _aidl_return) override;
+    ::ndk::ScopedAStatus getPartitionType(
+            const std::string& in_partitionName,
+            ::aidl::android::hardware::fastboot::FileSystemType* _aidl_return) override;
+    ::ndk::ScopedAStatus getVariant(std::string* _aidl_return) override;
+};
+
+}  // namespace fastboot
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/gatekeeper/1.0/vts/OWNERS b/gatekeeper/1.0/vts/OWNERS
index 738c710..ee2af97 100644
--- a/gatekeeper/1.0/vts/OWNERS
+++ b/gatekeeper/1.0/vts/OWNERS
@@ -1,3 +1,3 @@
-jdanis@google.com
+# Bug component: 1124862
 swillden@google.com
 guangzhu@google.com
diff --git a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
index f3fa0b4..e938b01 100644
--- a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
+++ b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
@@ -244,6 +244,47 @@
 }
 
 /**
+ * Ensure that passwords containing a NUL byte aren't truncated
+ */
+TEST_P(GatekeeperHidlTest, PasswordIsBinaryData) {
+  GatekeeperResponse enrollRsp;
+  GatekeeperResponse verifyRsp;
+  hidl_vec<uint8_t> rightPassword = {'A', 'B', 'C', '\0', 'D', 'E', 'F'};
+  hidl_vec<uint8_t> wrongPassword = {'A', 'B', 'C', '\0', '\0', '\0', '\0'};
+
+  ALOGI("Testing Enroll+Verify of password with embedded NUL (expected success)");
+  enrollNewPassword(rightPassword, enrollRsp, true);
+  verifyPassword(rightPassword, enrollRsp.data, 1, verifyRsp, true);
+
+  ALOGI("Testing Verify of wrong password (expected failure)");
+  verifyPassword(wrongPassword, enrollRsp.data, 1, verifyRsp, false);
+
+  ALOGI("PasswordIsBinaryData test done");
+}
+
+/**
+ * Ensure that long passwords aren't truncated
+ */
+TEST_P(GatekeeperHidlTest, LongPassword) {
+  GatekeeperResponse enrollRsp;
+  GatekeeperResponse verifyRsp;
+  hidl_vec<uint8_t> password;
+
+  password.resize(64); // maximum length used by Android
+  memset(password.data(), 'A', password.size());
+
+  ALOGI("Testing Enroll+Verify of long password (expected success)");
+  enrollNewPassword(password, enrollRsp, true);
+  verifyPassword(password, enrollRsp.data, 1, verifyRsp, true);
+
+  ALOGI("Testing Verify of wrong password (expected failure)");
+  password[password.size() - 1] ^= 1;
+  verifyPassword(password, enrollRsp.data, 1, verifyRsp, false);
+
+  ALOGI("LongPassword test done");
+}
+
+/**
  * Ensure we can securely update password (keep the same
  * secure user_id) if we prove we know old password
  */
diff --git a/gatekeeper/OWNERS b/gatekeeper/OWNERS
new file mode 100644
index 0000000..fddc2ff
--- /dev/null
+++ b/gatekeeper/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 1124862
+swillden@google.com
+guangzhu@google.com
+subrahmanyaman@google.com
diff --git a/gatekeeper/aidl/Android.bp b/gatekeeper/aidl/Android.bp
new file mode 100644
index 0000000..770e8ab
--- /dev/null
+++ b/gatekeeper/aidl/Android.bp
@@ -0,0 +1,29 @@
+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.gatekeeper",
+    vendor_available: true,
+    imports: [
+        "android.hardware.security.keymint-V3",
+    ],
+    srcs: ["android/hardware/gatekeeper/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            apps_enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+    },
+}
diff --git a/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/GatekeeperEnrollResponse.aidl b/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/GatekeeperEnrollResponse.aidl
new file mode 100644
index 0000000..ae64ffc
--- /dev/null
+++ b/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/GatekeeperEnrollResponse.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gatekeeper;
+@VintfStability
+parcelable GatekeeperEnrollResponse {
+  int statusCode;
+  int timeoutMs;
+  long secureUserId;
+  byte[] data;
+}
diff --git a/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/GatekeeperVerifyResponse.aidl b/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/GatekeeperVerifyResponse.aidl
new file mode 100644
index 0000000..f55da30
--- /dev/null
+++ b/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/GatekeeperVerifyResponse.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gatekeeper;
+@VintfStability
+parcelable GatekeeperVerifyResponse {
+  int statusCode;
+  int timeoutMs;
+  android.hardware.security.keymint.HardwareAuthToken hardwareAuthToken;
+}
diff --git a/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/IGatekeeper.aidl b/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/IGatekeeper.aidl
new file mode 100644
index 0000000..1a6f1ff
--- /dev/null
+++ b/gatekeeper/aidl/aidl_api/android.hardware.gatekeeper/current/android/hardware/gatekeeper/IGatekeeper.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.gatekeeper;
+@SensitiveData @VintfStability
+interface IGatekeeper {
+  void deleteAllUsers();
+  void deleteUser(in int uid);
+  android.hardware.gatekeeper.GatekeeperEnrollResponse enroll(in int uid, in byte[] currentPasswordHandle, in byte[] currentPassword, in byte[] desiredPassword);
+  android.hardware.gatekeeper.GatekeeperVerifyResponse verify(in int uid, in long challenge, in byte[] enrolledPasswordHandle, in byte[] providedPassword);
+  const int STATUS_REENROLL = 1;
+  const int STATUS_OK = 0;
+  const int ERROR_GENERAL_FAILURE = -1;
+  const int ERROR_RETRY_TIMEOUT = -2;
+  const int ERROR_NOT_IMPLEMENTED = -3;
+}
diff --git a/gatekeeper/aidl/android/hardware/gatekeeper/GatekeeperEnrollResponse.aidl b/gatekeeper/aidl/android/hardware/gatekeeper/GatekeeperEnrollResponse.aidl
new file mode 100644
index 0000000..04bacf0
--- /dev/null
+++ b/gatekeeper/aidl/android/hardware/gatekeeper/GatekeeperEnrollResponse.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.gatekeeper;
+
+/**
+ * Gatekeeper response to enroll requests has this structure as mandatory part
+ */
+@VintfStability
+parcelable GatekeeperEnrollResponse {
+    /**
+     * Request completion status
+     */
+    int statusCode;
+    /**
+     * Retry timeout in ms, if code == ERROR_RETRY_TIMEOUT
+     * otherwise unused (0)
+     */
+    int timeoutMs;
+    /**
+     * secure user id.
+     */
+    long secureUserId;
+    /**
+     * optional crypto blob. Opaque to Android system.
+     */
+    byte[] data;
+}
diff --git a/gatekeeper/aidl/android/hardware/gatekeeper/GatekeeperVerifyResponse.aidl b/gatekeeper/aidl/android/hardware/gatekeeper/GatekeeperVerifyResponse.aidl
new file mode 100644
index 0000000..bcf2d76
--- /dev/null
+++ b/gatekeeper/aidl/android/hardware/gatekeeper/GatekeeperVerifyResponse.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.gatekeeper;
+
+import android.hardware.security.keymint.HardwareAuthToken;
+
+/**
+ * Gatekeeper response to verify requests has this structure as mandatory part
+ */
+@VintfStability
+parcelable GatekeeperVerifyResponse {
+    /**
+     * Request completion status
+     */
+    int statusCode;
+    /**
+     * Retry timeout in ms, if code == ERROR_RETRY_TIMEOUT
+     * otherwise unused (0)
+     */
+    int timeoutMs;
+    /**
+     * On successful verification of the password,
+     * IGatekeeper implementations must return hardware auth token
+     * in the response.
+     */
+    HardwareAuthToken hardwareAuthToken;
+}
diff --git a/gatekeeper/aidl/android/hardware/gatekeeper/IGatekeeper.aidl b/gatekeeper/aidl/android/hardware/gatekeeper/IGatekeeper.aidl
new file mode 100644
index 0000000..927293e
--- /dev/null
+++ b/gatekeeper/aidl/android/hardware/gatekeeper/IGatekeeper.aidl
@@ -0,0 +1,146 @@
+/*
+ * 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.gatekeeper;
+
+import android.hardware.gatekeeper.GatekeeperEnrollResponse;
+import android.hardware.gatekeeper.GatekeeperVerifyResponse;
+
+@VintfStability
+@SensitiveData
+interface IGatekeeper {
+    /**
+     * enroll and verify binder calls may return a ServiceSpecificException
+     * with the following error codes.
+     */
+    /* Success, but upper layers should re-enroll the verified password due to a version change. */
+    const int STATUS_REENROLL = 1;
+    /* operation is successful */
+    const int STATUS_OK = 0;
+    /* operation is successful. */
+    const int ERROR_GENERAL_FAILURE = -1;
+    /* operation should  be retried after timeout. */
+    const int ERROR_RETRY_TIMEOUT = -2;
+    /* operation is not implemented. */
+    const int ERROR_NOT_IMPLEMENTED = -3;
+
+    /**
+     * Deletes all the enrolled_password_handles for all uid's. Once called,
+     * no users must be enrolled on the device.
+     * This is an optional method.
+     *
+     * Service status return:
+     *
+     * OK if all the users are deleted successfully.
+     * ERROR_GENERAL_FAILURE on failure.
+     * ERROR_NOT_IMPLEMENTED if not implemented.
+     */
+    void deleteAllUsers();
+
+    /**
+     * Deletes the enrolledPasswordHandle associated with the uid. Once deleted
+     * the user cannot be verified anymore.
+     * This is an optional method.
+     *
+     * Service status return:
+     *
+     * OK if user is deleted successfully.
+     * ERROR_GENERAL_FAILURE on failure.
+     * ERROR_NOT_IMPLEMENTED if not implemented.
+     *
+     * @param uid The Android user identifier
+     */
+    void deleteUser(in int uid);
+
+    /**
+     * Enrolls desiredPassword, which may be derived from a user selected pin
+     * or password, with the private key used only for enrolling authentication
+     * factor data.
+     *
+     * If there was already a password enrolled, current password handle must be
+     * passed in currentPasswordHandle, and current password must be passed in
+     * currentPassword. Valid currentPassword must verify() against
+     * currentPasswordHandle.
+     *
+     * Service status return:
+     *
+     * OK if password is enrolled successfully.
+     * ERROR_GENERAL_FAILURE on failure.
+     * ERROR_NOT_IMPLEMENTED if not implemented.
+     *
+     * @param uid The Android user identifier
+     *
+     * @param currentPasswordHandle The currently enrolled password handle the user
+     *    wants to replace. May be empty only if there's no currently enrolled
+     *    password. Otherwise must be non-empty.
+     *
+     * @param currentPassword The user's current password in plain text.
+     *    it MUST verify against current_password_handle if the latter is not-empty
+     *
+     * @param desiredPassword The new password the user wishes to enroll in
+     *    plaintext.
+     *
+     * @return
+     *    On success, data buffer must contain the new password handle referencing
+     *    the password provided in desiredPassword.
+     *    This buffer can be used on subsequent calls to enroll or
+     *    verify. response.statusCode must contain either ERROR_RETRY_TIMEOUT or
+     *    STATUS_OK. On error, this buffer must be empty. This method may return
+     *    ERROR_GENERAL_FAILURE on failure.
+     *    If ERROR_RETRY_TIMEOUT is returned, response.timeout must be non-zero.
+     */
+    GatekeeperEnrollResponse enroll(in int uid, in byte[] currentPasswordHandle,
+            in byte[] currentPassword, in byte[] desiredPassword);
+
+    /**
+     * Verifies that providedPassword matches enrolledPasswordHandle.
+     *
+     * Implementations of this module may retain the result of this call
+     * to attest to the recency of authentication.
+     *
+     * On success, returns verification token in response.data, which shall be
+     * usable to attest password verification to other trusted services.
+     *
+     * Service status return:
+     *
+     * OK if password is enrolled successfully.
+     * ERROR_GENERAL_FAILURE on failure.
+     * ERROR_NOT_IMPLEMENTED if not implemented.
+     *
+     * @param uid The Android user identifier
+     *
+     * @param challenge An optional challenge to authenticate against, or 0.
+     *    Used when a separate authenticator requests password verification,
+     *    or for transactional password authentication.
+     *
+     * @param enrolledPasswordHandle The currently enrolled password handle that
+     *    user wishes to verify against. Must be non-empty.
+     *
+     * @param providedPassword The plaintext password to be verified against the
+     *    enrolledPasswordHandle
+     *
+     * @return
+     *    On success, a HardwareAuthToken resulting from this verification is returned.
+     *    response.statusCode must contain either ERROR_RETRY_TIMEOUT or
+     *    or STATUS_REENROLL or STATUS_OK.
+     *    On error, data buffer must be empty.
+     *    This method may return ERROR_GENERAL_FAILURE on failure.
+     *    If password re-enrollment is necessary, it must return STATUS_REENROLL.
+     *    If ERROR_RETRY_TIMEOUT is returned, response.timeout must be non-zero.
+     */
+    GatekeeperVerifyResponse verify(in int uid, in long challenge, in byte[] enrolledPasswordHandle,
+            in byte[] providedPassword);
+}
diff --git a/gatekeeper/aidl/vts/functional/Android.bp b/gatekeeper/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..2fa80de
--- /dev/null
+++ b/gatekeeper/aidl/vts/functional/Android.bp
@@ -0,0 +1,39 @@
+//
+// 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
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsHalGatekeeperTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+        "keymint_use_latest_hal_aidl_ndk_shared",
+    ],
+    srcs: ["VtsHalGatekeeperTargetTest.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+        "libbase",
+    ],
+    static_libs: ["android.hardware.gatekeeper-V1-ndk"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp b/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
new file mode 100644
index 0000000..c89243b
--- /dev/null
+++ b/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
@@ -0,0 +1,413 @@
+/*
+ * 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 "gatekeeper_aidl_hal_test"
+
+#include <inttypes.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <cmath>
+#include <string>
+#include <vector>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/gatekeeper/GatekeeperEnrollResponse.h>
+#include <aidl/android/hardware/gatekeeper/GatekeeperVerifyResponse.h>
+#include <aidl/android/hardware/gatekeeper/IGatekeeper.h>
+#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
+#include <android-base/endian.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <hardware/hw_auth_token.h>
+
+#include <log/log.h>
+
+using aidl::android::hardware::gatekeeper::GatekeeperEnrollResponse;
+using aidl::android::hardware::gatekeeper::GatekeeperVerifyResponse;
+using aidl::android::hardware::gatekeeper::IGatekeeper;
+using aidl::android::hardware::security::keymint::HardwareAuthToken;
+using Status = ::ndk::ScopedAStatus;
+
+struct GatekeeperRequest {
+    uint32_t uid;
+    uint64_t challenge;
+    std::vector<uint8_t> curPwdHandle;
+    std::vector<uint8_t> curPwd;
+    std::vector<uint8_t> newPwd;
+    GatekeeperRequest() : uid(0), challenge(0) {}
+};
+
+// ASSERT_* macros generate return "void" internally
+// we have to use EXPECT_* if we return anything but "void"
+static void verifyAuthToken(GatekeeperVerifyResponse& rsp) {
+    uint32_t auth_type = static_cast<uint32_t>(rsp.hardwareAuthToken.authenticatorType);
+    uint64_t auth_tstamp = static_cast<uint64_t>(rsp.hardwareAuthToken.timestamp.milliSeconds);
+
+    EXPECT_EQ(HW_AUTH_PASSWORD, auth_type);
+    EXPECT_NE(UINT64_C(~0), auth_tstamp);
+    ALOGI("Authenticator ID: %016" PRIX64, rsp.hardwareAuthToken.authenticatorId);
+    EXPECT_NE(UINT32_C(0), rsp.hardwareAuthToken.userId);
+}
+
+// The main test class for Gatekeeper AIDL HAL.
+class GatekeeperAidlTest : public ::testing::TestWithParam<std::string> {
+  protected:
+    void setUid(uint32_t uid) { uid_ = uid; }
+
+    Status doEnroll(GatekeeperRequest& req, GatekeeperEnrollResponse& rsp) {
+        Status ret;
+        while (true) {
+            ret = gatekeeper_->enroll(uid_, req.curPwdHandle, req.curPwd, req.newPwd, &rsp);
+            if (ret.isOk()) break;
+            if (getReturnStatusCode(ret) != IGatekeeper::ERROR_RETRY_TIMEOUT) break;
+            ALOGI("%s: got retry code; retrying in 1 sec", __func__);
+            sleep(1);
+        }
+        return ret;
+    }
+
+    Status doVerify(GatekeeperRequest& req, GatekeeperVerifyResponse& rsp) {
+        Status ret;
+        while (true) {
+            ret = gatekeeper_->verify(uid_, req.challenge, req.curPwdHandle, req.newPwd, &rsp);
+            if (ret.isOk()) break;
+            if (getReturnStatusCode(ret) != IGatekeeper::ERROR_RETRY_TIMEOUT) break;
+            ALOGI("%s: got retry code; retrying in 1 sec", __func__);
+            sleep(1);
+        }
+        return ret;
+    }
+
+    Status doDeleteUser() { return gatekeeper_->deleteUser(uid_); }
+
+    Status doDeleteAllUsers() { return gatekeeper_->deleteAllUsers(); }
+
+    void generatePassword(std::vector<uint8_t>& password, uint8_t seed) {
+        password.resize(16);
+        memset(password.data(), seed, password.size());
+    }
+
+    void checkEnroll(GatekeeperEnrollResponse& rsp, Status& ret, bool expectSuccess) {
+        if (expectSuccess) {
+            EXPECT_TRUE(ret.isOk());
+            EXPECT_EQ(IGatekeeper::STATUS_OK, rsp.statusCode);
+            EXPECT_NE(nullptr, rsp.data.data());
+            EXPECT_GT(rsp.data.size(), UINT32_C(0));
+            EXPECT_NE(UINT32_C(0), rsp.secureUserId);
+        } else {
+            EXPECT_EQ(IGatekeeper::ERROR_GENERAL_FAILURE, getReturnStatusCode(ret));
+            EXPECT_EQ(UINT32_C(0), rsp.data.size());
+        }
+    }
+
+    void checkVerify(GatekeeperVerifyResponse& rsp, Status& ret, uint64_t challenge,
+                     bool expectSuccess) {
+        if (expectSuccess) {
+            EXPECT_TRUE(ret.isOk());
+            EXPECT_GE(rsp.statusCode, IGatekeeper::STATUS_OK);
+            EXPECT_LE(rsp.statusCode, IGatekeeper::STATUS_REENROLL);
+
+            verifyAuthToken(rsp);
+            EXPECT_EQ(challenge, rsp.hardwareAuthToken.challenge);
+        } else {
+            EXPECT_EQ(IGatekeeper::ERROR_GENERAL_FAILURE, getReturnStatusCode(ret));
+        }
+    }
+
+    void enrollNewPassword(std::vector<uint8_t>& password, GatekeeperEnrollResponse& rsp,
+                           bool expectSuccess) {
+        GatekeeperRequest req;
+        req.newPwd = password;
+        Status ret = doEnroll(req, rsp);
+        checkEnroll(rsp, ret, expectSuccess);
+    }
+
+    void verifyPassword(std::vector<uint8_t>& password, std::vector<uint8_t>& passwordHandle,
+                        uint64_t challenge, GatekeeperVerifyResponse& verifyRsp,
+                        bool expectSuccess) {
+        GatekeeperRequest verifyReq;
+
+        // build verify request for the same password (we want it to succeed)
+        verifyReq.newPwd = password;
+        // use enrolled password handle we've got
+        verifyReq.curPwdHandle = passwordHandle;
+        verifyReq.challenge = challenge;
+        Status ret = doVerify(verifyReq, verifyRsp);
+        checkVerify(verifyRsp, ret, challenge, expectSuccess);
+    }
+
+    int32_t getReturnStatusCode(const Status& result) {
+        if (!result.isOk()) {
+            if (result.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+                return result.getServiceSpecificError();
+            }
+            return IGatekeeper::ERROR_GENERAL_FAILURE;
+        }
+        return IGatekeeper::STATUS_OK;
+    }
+
+  protected:
+    std::shared_ptr<IGatekeeper> gatekeeper_;
+    uint32_t uid_;
+
+  public:
+    GatekeeperAidlTest() : uid_(0) {}
+    virtual void SetUp() override {
+        gatekeeper_ = IGatekeeper::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+        ASSERT_NE(nullptr, gatekeeper_.get());
+        doDeleteAllUsers();
+    }
+
+    virtual void TearDown() override { doDeleteAllUsers(); }
+};
+
+/**
+ * Ensure we can enroll new password
+ */
+TEST_P(GatekeeperAidlTest, EnrollSuccess) {
+    std::vector<uint8_t> password;
+    GatekeeperEnrollResponse rsp;
+    ALOGI("Testing Enroll (expected success)");
+    generatePassword(password, 0);
+    enrollNewPassword(password, rsp, true);
+    ALOGI("Testing Enroll done");
+}
+
+/**
+ * Ensure we can not enroll empty password
+ */
+TEST_P(GatekeeperAidlTest, EnrollNoPassword) {
+    std::vector<uint8_t> password;
+    GatekeeperEnrollResponse rsp;
+    ALOGI("Testing Enroll (expected failure)");
+    enrollNewPassword(password, rsp, false);
+    ALOGI("Testing Enroll done");
+}
+
+/**
+ * Ensure we can successfully verify previously enrolled password
+ */
+TEST_P(GatekeeperAidlTest, VerifySuccess) {
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    std::vector<uint8_t> password;
+
+    ALOGI("Testing Enroll+Verify (expected success)");
+    generatePassword(password, 0);
+    enrollNewPassword(password, enrollRsp, true);
+    verifyPassword(password, enrollRsp.data, 1, verifyRsp, true);
+
+    ALOGI("Testing unenrolled password doesn't verify");
+    verifyRsp = {0, 0, {}};
+    generatePassword(password, 1);
+    verifyPassword(password, enrollRsp.data, 1, verifyRsp, false);
+    ALOGI("Testing Enroll+Verify done");
+}
+
+/**
+ * Ensure we can securely update password (keep the same
+ * secure user_id) if we prove we know old password
+ */
+TEST_P(GatekeeperAidlTest, TrustedReenroll) {
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperRequest reenrollReq;
+    GatekeeperEnrollResponse reenrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    GatekeeperVerifyResponse reenrollVerifyRsp;
+    std::vector<uint8_t> password;
+    std::vector<uint8_t> newPassword;
+
+    generatePassword(password, 0);
+
+    ALOGI("Testing Trusted Reenroll (expected success)");
+    enrollNewPassword(password, enrollRsp, true);
+    verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
+    ALOGI("Primary Enroll+Verify done");
+
+    generatePassword(newPassword, 1);
+    reenrollReq.newPwd = newPassword;
+    reenrollReq.curPwd = password;
+    reenrollReq.curPwdHandle = enrollRsp.data;
+
+    Status ret = doEnroll(reenrollReq, reenrollRsp);
+    checkEnroll(reenrollRsp, ret, true);
+    verifyPassword(newPassword, reenrollRsp.data, 0, reenrollVerifyRsp, true);
+    ALOGI("Trusted ReEnroll+Verify done");
+
+    verifyAuthToken(verifyRsp);
+    verifyAuthToken(reenrollVerifyRsp);
+    EXPECT_EQ(verifyRsp.hardwareAuthToken.userId, reenrollVerifyRsp.hardwareAuthToken.userId);
+    ALOGI("Testing Trusted Reenroll done");
+}
+
+/**
+ * Ensure we can update password (and get new
+ * secure user_id) if we don't know old password
+ */
+TEST_P(GatekeeperAidlTest, UntrustedReenroll) {
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperEnrollResponse reenrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    GatekeeperVerifyResponse reenrollVerifyRsp;
+    std::vector<uint8_t> password;
+    std::vector<uint8_t> newPassword;
+
+    ALOGI("Testing Untrusted Reenroll (expected success)");
+    generatePassword(password, 0);
+    enrollNewPassword(password, enrollRsp, true);
+    verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
+    ALOGI("Primary Enroll+Verify done");
+
+    generatePassword(newPassword, 1);
+    enrollNewPassword(newPassword, reenrollRsp, true);
+    verifyPassword(newPassword, reenrollRsp.data, 0, reenrollVerifyRsp, true);
+    ALOGI("Untrusted ReEnroll+Verify done");
+
+    verifyAuthToken(verifyRsp);
+    verifyAuthToken(reenrollVerifyRsp);
+    EXPECT_NE(verifyRsp.hardwareAuthToken.userId, reenrollVerifyRsp.hardwareAuthToken.userId);
+    ALOGI("Testing Untrusted Reenroll done");
+}
+
+/**
+ * Ensure we don't get successful verify with invalid data
+ */
+TEST_P(GatekeeperAidlTest, VerifyNoData) {
+    std::vector<uint8_t> password;
+    std::vector<uint8_t> passwordHandle;
+    GatekeeperVerifyResponse verifyRsp;
+
+    ALOGI("Testing Verify (expected failure)");
+    verifyPassword(password, passwordHandle, 0, verifyRsp, false);
+    ALOGI("Testing Verify done");
+}
+
+/**
+ * Ensure we can not verify password after we enrolled it and then deleted user
+ */
+TEST_P(GatekeeperAidlTest, DeleteUserTest) {
+    std::vector<uint8_t> password;
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    ALOGI("Testing deleteUser (expected success)");
+    setUid(10001);
+    generatePassword(password, 0);
+    enrollNewPassword(password, enrollRsp, true);
+    verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
+    ALOGI("Enroll+Verify done");
+    auto result = doDeleteUser();
+    EXPECT_TRUE(result.isOk() ||
+                (getReturnStatusCode(result) == IGatekeeper::ERROR_NOT_IMPLEMENTED));
+    ALOGI("DeleteUser done");
+    if (result.isOk()) {
+        verifyRsp = {0, 0, {}};
+        verifyPassword(password, enrollRsp.data, 0, verifyRsp, false);
+        ALOGI("Verify after Delete done (must fail)");
+    }
+    ALOGI("Testing deleteUser done: rsp=%" PRIi32, getReturnStatusCode(result));
+}
+
+/**
+ * Ensure we can not delete a user that does not exist
+ */
+TEST_P(GatekeeperAidlTest, DeleteInvalidUserTest) {
+    std::vector<uint8_t> password;
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    ALOGI("Testing deleteUser (expected failure)");
+    setUid(10002);
+    generatePassword(password, 0);
+    enrollNewPassword(password, enrollRsp, true);
+    verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
+    ALOGI("Enroll+Verify done");
+
+    // Delete the user
+    Status result1 = doDeleteUser();
+    EXPECT_TRUE(result1.isOk() ||
+                (getReturnStatusCode(result1) == IGatekeeper::ERROR_NOT_IMPLEMENTED));
+
+    // Delete the user again
+    Status result2 = doDeleteUser();
+    int32_t retCode2 = getReturnStatusCode(result2);
+    EXPECT_TRUE((retCode2 == IGatekeeper::ERROR_NOT_IMPLEMENTED) ||
+                (retCode2 == IGatekeeper::ERROR_GENERAL_FAILURE));
+    ALOGI("DeleteUser done");
+    ALOGI("Testing deleteUser done: rsp=%" PRIi32, retCode2);
+}
+
+/**
+ * Ensure we can not verify passwords after we enrolled them and then deleted
+ * all users
+ */
+TEST_P(GatekeeperAidlTest, DeleteAllUsersTest) {
+    struct UserData {
+        uint32_t userId;
+        std::vector<uint8_t> password;
+        GatekeeperEnrollResponse enrollRsp;
+        GatekeeperVerifyResponse verifyRsp;
+        UserData(int id) { userId = id; }
+    } users[3]{10001, 10002, 10003};
+    ALOGI("Testing deleteAllUsers (expected success)");
+
+    // enroll multiple users
+    for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
+        setUid(users[i].userId);
+        generatePassword(users[i].password, (i % 255) + 1);
+        enrollNewPassword(users[i].password, users[i].enrollRsp, true);
+    }
+    ALOGI("Multiple users enrolled");
+
+    // verify multiple users
+    for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
+        setUid(users[i].userId);
+        verifyPassword(users[i].password, users[i].enrollRsp.data, 0, users[i].verifyRsp, true);
+    }
+    ALOGI("Multiple users verified");
+
+    Status result = doDeleteAllUsers();
+    EXPECT_TRUE(result.isOk() ||
+                (getReturnStatusCode(result) == IGatekeeper::ERROR_NOT_IMPLEMENTED));
+    ALOGI("All users deleted");
+
+    if (result.isOk()) {
+        // verify multiple users after they are deleted; all must fail
+        for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
+            setUid(users[i].userId);
+            users[i].verifyRsp = {0, 0, {}};
+            verifyPassword(users[i].password, users[i].enrollRsp.data, 0, users[i].verifyRsp,
+                           false);
+        }
+        ALOGI("Multiple users verified after delete (all must fail)");
+    }
+
+    ALOGI("Testing deleteAllUsers done: rsp=%" PRIi32, getReturnStatusCode(result));
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GatekeeperAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, GatekeeperAidlTest,
+    testing::ValuesIn(android::getAidlHalInstanceNames(IGatekeeper::descriptor)),
+    android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/gnss/aidl/Android.bp b/gnss/aidl/Android.bp
index 9f9090c..f45fe5d 100644
--- a/gnss/aidl/Android.bp
+++ b/gnss/aidl/Android.bp
@@ -36,11 +36,6 @@
         java: {
             platform_apis: true,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl
index f0b583d..aaafe7f 100644
--- a/gnss/aidl/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl
@@ -104,7 +104,7 @@
      *
      * The framework calls this method to instruct the GPS engine to prepare for serving requests
      * from the framework. The GNSS HAL implementation must respond to all GNSS requests from the
-     * framework upon successful return from this method until cleanup() method is called to
+     * framework upon successful return from this method until close() method is called to
      * close this interface.
      *
      * @param callback Callback interface for IGnss.
diff --git a/gnss/aidl/vts/gnss_hal_test.cpp b/gnss/aidl/vts/gnss_hal_test.cpp
index 0e1218e..3907f57 100644
--- a/gnss/aidl/vts/gnss_hal_test.cpp
+++ b/gnss/aidl/vts/gnss_hal_test.cpp
@@ -107,6 +107,17 @@
     }
 }
 
+void GnssHalTest::TearDown() {
+    GnssHalTestTemplate<IGnss_V2_1>::TearDown();
+    if (aidl_gnss_hal_ != nullptr) {
+        aidl_gnss_hal_->close();
+        aidl_gnss_hal_ = nullptr;
+    }
+
+    // Set to nullptr to destruct the callback event queues and warn of any unprocessed events.
+    aidl_gnss_cb_ = nullptr;
+}
+
 void GnssHalTest::CheckLocation(const GnssLocation& location, bool check_speed) {
     Utils::checkLocation(location, check_speed, /* check_more_accuracies= */ true);
 }
diff --git a/gnss/aidl/vts/gnss_hal_test.h b/gnss/aidl/vts/gnss_hal_test.h
index 645fc82..c49c1b9 100644
--- a/gnss/aidl/vts/gnss_hal_test.h
+++ b/gnss/aidl/vts/gnss_hal_test.h
@@ -64,6 +64,7 @@
 
     virtual void SetUp() override;
     virtual void SetUpGnssCallback() override;
+    virtual void TearDown() override;
 
     void CheckLocation(const android::hardware::gnss::GnssLocation& location,
                        const bool check_speed);
diff --git a/graphics/bufferqueue/1.0/Android.bp b/graphics/bufferqueue/1.0/Android.bp
index 11559b2..82c71f1 100644
--- a/graphics/bufferqueue/1.0/Android.bp
+++ b/graphics/bufferqueue/1.0/Android.bp
@@ -27,7 +27,7 @@
     gen_java: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
         "com.android.media",
         "com.android.media.swcodec",
     ],
diff --git a/graphics/bufferqueue/2.0/Android.bp b/graphics/bufferqueue/2.0/Android.bp
index 552daff..3067e24 100644
--- a/graphics/bufferqueue/2.0/Android.bp
+++ b/graphics/bufferqueue/2.0/Android.bp
@@ -29,7 +29,7 @@
     gen_java: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
         "com.android.media",
         "com.android.media.swcodec",
     ],
diff --git a/graphics/common/1.0/Android.bp b/graphics/common/1.0/Android.bp
index 19c51cd..3288583 100644
--- a/graphics/common/1.0/Android.bp
+++ b/graphics/common/1.0/Android.bp
@@ -23,7 +23,7 @@
     gen_java_constants: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
         "com.android.media.swcodec",
         "test_com.android.media.swcodec",
     ],
diff --git a/graphics/common/1.1/Android.bp b/graphics/common/1.1/Android.bp
index 0f1b5bf..5d07eae 100644
--- a/graphics/common/1.1/Android.bp
+++ b/graphics/common/1.1/Android.bp
@@ -26,7 +26,7 @@
     gen_java_constants: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
         "com.android.media.swcodec",
         "test_com.android.media.swcodec",
     ],
diff --git a/graphics/common/1.2/Android.bp b/graphics/common/1.2/Android.bp
index ce3350d..4aa4af5 100644
--- a/graphics/common/1.2/Android.bp
+++ b/graphics/common/1.2/Android.bp
@@ -27,7 +27,7 @@
     gen_java_constants: true,
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
         "com.android.media.swcodec",
         "test_com.android.media.swcodec",
     ],
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp b/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp
index 0171dd6..3527cca 100644
--- a/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp
@@ -25,7 +25,6 @@
     name: "libhwc2on1adapter",
     vendor: true,
 
-    clang: true,
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp b/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp
index 3965d12..d613ba9 100644
--- a/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp
+++ b/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp
@@ -25,7 +25,6 @@
     name: "libhwc2onfbadapter",
     vendor: true,
 
-    clang: true,
     cflags: [
         "-Wall",
         "-Wextra",
@@ -37,6 +36,9 @@
     ],
 
     header_libs: ["libhardware_headers"],
-    shared_libs: ["liblog", "libsync"],
+    shared_libs: [
+        "liblog",
+        "libsync",
+    ],
     export_include_dirs: ["include"],
 }
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.cpp b/graphics/composer/aidl/vts/VtsComposerClient.cpp
index 2b60703..5bc7296 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.cpp
+++ b/graphics/composer/aidl/vts/VtsComposerClient.cpp
@@ -488,10 +488,13 @@
 }
 
 bool VtsComposerClient::destroyAllLayers() {
-    for (const auto& it : mDisplayResources) {
-        const auto& [display, resource] = it;
+    std::unordered_map<int64_t, DisplayResource> physicalDisplays;
+    while (!mDisplayResources.empty()) {
+        const auto& it = mDisplayResources.begin();
+        const auto& [display, resource] = *it;
 
-        for (auto layer : resource.layers) {
+        while (!resource.layers.empty()) {
+            auto layer = *resource.layers.begin();
             const auto status = destroyLayer(display, layer);
             if (!status.isOk()) {
                 ALOGE("Unable to destroy all the layers, failed at layer %" PRId64 " with error %s",
@@ -507,8 +510,12 @@
                       status.getDescription().c_str());
                 return false;
             }
+        } else {
+            auto extractIter = mDisplayResources.extract(it);
+            physicalDisplays.insert(std::move(extractIter));
         }
     }
+    mDisplayResources.swap(physicalDisplays);
     mDisplayResources.clear();
     return true;
 }
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
index db7e67d..5f0a176 100644
--- a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
@@ -259,19 +259,22 @@
 
         for (int i = 0; i < 3; i++) {
             const auto& plane = flex.planes[i];
-            // must have 8-bit depth
-            if (plane.bits_per_component != 8 || plane.bits_used != 8) {
+            // Must be a positive multiple of 8.
+            if (plane.bits_per_component <= 0 || (plane.bits_per_component % 8) != 0) {
                 return false;
             }
-
+            // Must be between 1 and bits_per_component, inclusive.
+            if (plane.bits_used < 1 || plane.bits_used > plane.bits_per_component) {
+                return false;
+            }
             if (plane.component == FLEX_COMPONENT_Y) {
                 // Y must not be interleaved
-                if (plane.h_increment != 1) {
+                if (plane.h_increment != 1 && plane.h_increment != 2) {
                     return false;
                 }
             } else {
                 // Cb and Cr can be interleaved
-                if (plane.h_increment != 1 && plane.h_increment != 2) {
+                if (plane.h_increment != 1 && plane.h_increment != 2 && plane.h_increment != 4) {
                     return false;
                 }
             }
diff --git a/health/aidl/Android.bp b/health/aidl/Android.bp
index f0cd33f..a4d4ace 100644
--- a/health/aidl/Android.bp
+++ b/health/aidl/Android.bp
@@ -36,11 +36,6 @@
             enabled: true,
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/health/aidl/default/Android.bp b/health/aidl/default/Android.bp
index 8eab997..4eb3cb1 100644
--- a/health/aidl/default/Android.bp
+++ b/health/aidl/default/Android.bp
@@ -159,3 +159,51 @@
     init_rc: ["android.hardware.health-service.example_recovery.rc"],
     overrides: ["charger.recovery"],
 }
+
+// AIDL Fuzz version of libhealth2impl.
+cc_library_static {
+    name: "fuzz_libhealth_aidl_impl",
+    defaults: [
+        "libhealth_aidl_common_defaults",
+        "libhealth_aidl_charger_defaults",
+    ],
+    recovery_available: true,
+    export_include_dirs: ["include"],
+    export_static_lib_headers: [
+        "libbatterymonitor",
+    ],
+    srcs: [
+        "ChargerUtils.cpp",
+        "health-convert.cpp",
+        "HalHealthLoop.cpp",
+        "Health.cpp",
+        "LinkedCallback.cpp",
+    ],
+    target: {
+        recovery: {
+            exclude_srcs: [
+                "ChargerUtils.cpp",
+            ],
+        },
+    },
+}
+
+cc_fuzz {
+    name: "android.hardware.health-service.aidl_fuzzer",
+    defaults: [
+        "libhealth_aidl_impl_user",
+        "service_fuzzer_defaults",
+    ],
+    static_libs: [
+        "android.hardware.health-V1-ndk",
+        "libbase",
+        "liblog",
+        "fuzz_libhealth_aidl_impl",
+    ],
+    srcs: ["fuzzer.cpp"],
+    fuzz_config: {
+        cc: [
+            "hamzeh@google.com",
+        ],
+    },
+}
diff --git a/health/aidl/default/fuzzer.cpp b/health/aidl/default/fuzzer.cpp
new file mode 100644
index 0000000..b7c6d39
--- /dev/null
+++ b/health/aidl/default/fuzzer.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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 <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include <android-base/logging.h>
+#include <android/binder_interface_utils.h>
+#include <health-impl/Health.h>
+#include <health/utils.h>
+
+using aidl::android::hardware::health::Health;
+using android::fuzzService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    auto config = std::make_unique<healthd_config>();
+    ::android::hardware::health::InitHealthdConfig(config.get());
+    auto binder = ndk::SharedRefBase::make<Health>("default", std::move(config));
+
+    fuzzService(binder->asBinder().get(), FuzzedDataProvider(data, size));
+
+    return 0;
+}
\ No newline at end of file
diff --git a/health/storage/aidl/Android.bp b/health/storage/aidl/Android.bp
index 4cd9263..c614efb 100644
--- a/health/storage/aidl/Android.bp
+++ b/health/storage/aidl/Android.bp
@@ -33,11 +33,6 @@
         java: {
             enabled: false,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions: ["1"],
 }
diff --git a/identity/aidl/Android.bp b/identity/aidl/Android.bp
index 920a4b9..a33d43c 100644
--- a/identity/aidl/Android.bp
+++ b/identity/aidl/Android.bp
@@ -14,7 +14,7 @@
         "android/hardware/identity/*.aidl",
     ],
     imports: [
-        "android.hardware.keymaster",
+        "android.hardware.keymaster-V3",
         "android.hardware.security.keymint",
     ],
     stability: "vintf",
@@ -23,9 +23,6 @@
             platform_apis: true,
         },
         ndk: {
-            vndk: {
-                enabled: true,
-            },
             apps_enabled: false,
         },
     },
@@ -62,3 +59,27 @@
     ],
 
 }
+
+// cc_defaults that includes the latest Identity AIDL library.
+// Modules that depend on Identity directly can include this cc_defaults to
+// avoid managing dependency versions explicitly.
+cc_defaults {
+    name: "identity_use_latest_hal_aidl_ndk_static",
+    static_libs: [
+        "android.hardware.identity-V5-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "identity_use_latest_hal_aidl_ndk_shared",
+    shared_libs: [
+        "android.hardware.identity-V5-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "identity_use_latest_hal_aidl_cpp_static",
+    static_libs: [
+        "android.hardware.identity-V5-cpp",
+    ],
+}
diff --git a/identity/aidl/default/Android.bp b/identity/aidl/default/Android.bp
index 31ab400..a57875a 100644
--- a/identity/aidl/default/Android.bp
+++ b/identity/aidl/default/Android.bp
@@ -10,6 +10,10 @@
 cc_library_static {
     name: "android.hardware.identity-libeic-hal-common",
     vendor_available: true,
+    defaults: [
+        "identity_use_latest_hal_aidl_ndk_static",
+        "keymint_use_latest_hal_aidl_ndk_static",
+    ],
     srcs: [
         "common/IdentityCredential.cpp",
         "common/IdentityCredentialStore.cpp",
@@ -40,9 +44,7 @@
         "libsoft_attestation_cert",
         "libpuresoftkeymasterdevice",
         "android.hardware.identity-support-lib",
-        "android.hardware.identity-V4-ndk",
         "android.hardware.keymaster-V3-ndk",
-        "android.hardware.security.keymint-V2-ndk",
     ],
 }
 
@@ -83,6 +85,7 @@
     vintf_fragments: ["identity-default.xml"],
     vendor: true,
     defaults: [
+        "identity_use_latest_hal_aidl_ndk_static",
         "keymint_use_latest_hal_aidl_ndk_static",
     ],
     cflags: [
@@ -106,7 +109,6 @@
         "libsoft_attestation_cert",
         "libpuresoftkeymasterdevice",
         "android.hardware.identity-support-lib",
-        "android.hardware.identity-V4-ndk",
         "android.hardware.keymaster-V3-ndk",
         "android.hardware.identity-libeic-hal-common",
         "android.hardware.identity-libeic-library",
diff --git a/identity/aidl/default/EicOpsImpl.cc b/identity/aidl/default/EicOpsImpl.cc
index 3fd9f1d..b6d324f 100644
--- a/identity/aidl/default/EicOpsImpl.cc
+++ b/identity/aidl/default/EicOpsImpl.cc
@@ -100,6 +100,7 @@
     if (size != EIC_SHA256_DIGEST_SIZE) {
         LOG(ERROR) << "Expected 32 bytes from HMAC_Final, got " << size;
     }
+    HMAC_CTX_cleanup(realCtx);
 }
 
 void eicOpsSha256Init(EicSha256Ctx* ctx) {
@@ -394,14 +395,17 @@
     }
 
     if (BN_bn2binpad(sig->r, signature, 32) != 32) {
+        ECDSA_SIG_free(sig);
         eicDebug("Error encoding r");
         return false;
     }
     if (BN_bn2binpad(sig->s, signature + 32, 32) != 32) {
+        ECDSA_SIG_free(sig);
         eicDebug("Error encoding s");
         return false;
     }
 
+    ECDSA_SIG_free(sig);
     return true;
 }
 
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index 51ab110..dd29819 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -11,6 +11,7 @@
     name: "VtsHalIdentityTargetTest",
     defaults: [
         "VtsHalTargetTestDefaults",
+        "identity_use_latest_hal_aidl_cpp_static",
         "keymint_use_latest_hal_aidl_cpp_static",
         "keymint_use_latest_hal_aidl_ndk_static",
         "use_libaidlvintf_gtest_helper_static",
@@ -46,7 +47,6 @@
         "libpuresoftkeymasterdevice",
         "android.hardware.keymaster@4.0",
         "android.hardware.identity-support-lib",
-        "android.hardware.identity-V4-cpp",
         "android.hardware.keymaster-V3-cpp",
         "android.hardware.keymaster-V3-ndk",
         "libkeymaster4support",
diff --git a/identity/aidl/vts/AndroidTest.xml b/identity/aidl/vts/AndroidTest.xml
new file mode 100644
index 0000000..67132b0
--- /dev/null
+++ b/identity/aidl/vts/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<configuration description="Runs VtsHalIdentityTargetTest.">
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push"
+                value="VtsHalIdentityTargetTest->/data/local/tmp/VtsHalIdentityTargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalIdentityTargetTest" />
+        <option name="native-test-timeout" value="300000"/>
+    </test>
+</configuration>
diff --git a/input/common/aidl/Android.bp b/input/common/aidl/Android.bp
index 390d8b5..95a14b2 100644
--- a/input/common/aidl/Android.bp
+++ b/input/common/aidl/Android.bp
@@ -9,6 +9,7 @@
 
 aidl_interface {
     name: "android.hardware.input.common",
+    host_supported: true,
     vendor_available: true,
     srcs: ["android/hardware/input/common/*.aidl"],
     stability: "vintf",
diff --git a/input/processor/aidl/Android.bp b/input/processor/aidl/Android.bp
index 354816e..773bb49 100644
--- a/input/processor/aidl/Android.bp
+++ b/input/processor/aidl/Android.bp
@@ -9,6 +9,7 @@
 
 aidl_interface {
     name: "android.hardware.input.processor",
+    host_supported: true,
     vendor_available: true,
     srcs: ["android/hardware/input/processor/*.aidl"],
     imports: [
diff --git a/ir/aidl/Android.bp b/ir/aidl/Android.bp
index 2485f5b..25f6c8f 100644
--- a/ir/aidl/Android.bp
+++ b/ir/aidl/Android.bp
@@ -33,11 +33,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/keymaster/3.0/default/OWNERS b/keymaster/3.0/default/OWNERS
deleted file mode 100644
index 335660d..0000000
--- a/keymaster/3.0/default/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-jdanis@google.com
-swillden@google.com
diff --git a/keymaster/3.0/vts/OWNERS b/keymaster/3.0/vts/OWNERS
deleted file mode 100644
index 846bb84..0000000
--- a/keymaster/3.0/vts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-drysdale@google.com
-jdanis@google.com
-swillden@google.com
-yim@google.com
-yuexima@google.com
diff --git a/keymaster/3.0/vts/functional/OWNERS b/keymaster/3.0/vts/functional/OWNERS
deleted file mode 100644
index 2ef9086..0000000
--- a/keymaster/3.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 189335
-swillden@google.com
diff --git a/keymaster/4.0/default/OWNERS b/keymaster/4.0/default/OWNERS
deleted file mode 100644
index 335660d..0000000
--- a/keymaster/4.0/default/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-jdanis@google.com
-swillden@google.com
diff --git a/keymaster/4.0/support/OWNERS b/keymaster/4.0/support/OWNERS
deleted file mode 100644
index a9efe66..0000000
--- a/keymaster/4.0/support/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-jdanis@google.com
-swillden@google.com
-jbires@google.com
diff --git a/keymaster/4.0/vts/OWNERS b/keymaster/4.0/vts/OWNERS
deleted file mode 100644
index 0d6fa6c..0000000
--- a/keymaster/4.0/vts/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-drysdale@google.com
-jbires@google.com
-jdanis@google.com
-swillden@google.com
-yim@google.com
-yuexima@google.com
diff --git a/keymaster/4.0/vts/functional/OWNERS b/keymaster/4.0/vts/functional/OWNERS
deleted file mode 100644
index 2ef9086..0000000
--- a/keymaster/4.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 189335
-swillden@google.com
diff --git a/keymaster/4.1/default/OWNERS b/keymaster/4.1/default/OWNERS
deleted file mode 100644
index 2b2ad2a..0000000
--- a/keymaster/4.1/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-swillden@google.com
-zeuthen@google.com
\ No newline at end of file
diff --git a/keymaster/4.1/support/OWNERS b/keymaster/4.1/support/OWNERS
deleted file mode 100644
index 2b2ad2a..0000000
--- a/keymaster/4.1/support/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-swillden@google.com
-zeuthen@google.com
\ No newline at end of file
diff --git a/keymaster/4.1/vts/OWNERS b/keymaster/4.1/vts/OWNERS
deleted file mode 100644
index 24ed042..0000000
--- a/keymaster/4.1/vts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-drysdale@google.com
-jbires@google.com
-jdanis@google.com
-swillden@google.com
-zeuthen@google.com
\ No newline at end of file
diff --git a/keymaster/4.1/vts/functional/OWNERS b/keymaster/4.1/vts/functional/OWNERS
deleted file mode 100644
index 2ef9086..0000000
--- a/keymaster/4.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 189335
-swillden@google.com
diff --git a/keymaster/OWNERS b/keymaster/OWNERS
new file mode 100644
index 0000000..ac8bd83
--- /dev/null
+++ b/keymaster/OWNERS
@@ -0,0 +1,14 @@
+# Bug component: 1084733
+
+# Please assign all bugs related to /hardware/interfaces/keymaster to the team alias:
+#
+#    android-hardware-security@google.com
+#
+# This will get them auto-assigned to the on-call triage engineer, ensuring quickest response.
+
+drysdale@google.com
+eranm@google.com
+hasinitg@google.com
+jbires@google.com
+swillden@google.com
+zeuthen@google.com
diff --git a/keymaster/aidl/Android.bp b/keymaster/aidl/Android.bp
index c4b6740..0fb6e4c 100644
--- a/keymaster/aidl/Android.bp
+++ b/keymaster/aidl/Android.bp
@@ -18,11 +18,6 @@
         java: {
             platform_apis: true,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions: [
         "1",
diff --git a/light/aidl/Android.bp b/light/aidl/Android.bp
index 6f478d7..c11934f 100644
--- a/light/aidl/Android.bp
+++ b/light/aidl/Android.bp
@@ -18,11 +18,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/light/aidl/default/Lights.cpp b/light/aidl/default/Lights.cpp
index 74747d5..9bf3b20 100644
--- a/light/aidl/default/Lights.cpp
+++ b/light/aidl/default/Lights.cpp
@@ -23,12 +23,21 @@
 namespace hardware {
 namespace light {
 
+static constexpr int kNumDefaultLights = 3;
+
 ndk::ScopedAStatus Lights::setLightState(int id, const HwLightState& state) {
     LOG(INFO) << "Lights setting state for id=" << id << " to color " << std::hex << state.color;
-    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    if (id <= 0 || id > kNumDefaultLights) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    } else {
+        return ndk::ScopedAStatus::ok();
+    }
 }
 
-ndk::ScopedAStatus Lights::getLights(std::vector<HwLight>* /*lights*/) {
+ndk::ScopedAStatus Lights::getLights(std::vector<HwLight>* lights) {
+    for (int i = 1; i <= kNumDefaultLights; i++) {
+        lights->push_back({i, i});
+    }
     LOG(INFO) << "Lights reporting supported lights";
     return ndk::ScopedAStatus::ok();
 }
diff --git a/light/aidl/default/Lights.h b/light/aidl/default/Lights.h
index 8cba5a1..cba147f 100644
--- a/light/aidl/default/Lights.h
+++ b/light/aidl/default/Lights.h
@@ -23,10 +23,10 @@
 namespace hardware {
 namespace light {
 
-// Default implementation that reports no supported lights.
+// Default implementation that reports a few placeholder lights.
 class Lights : public BnLights {
     ndk::ScopedAStatus setLightState(int id, const HwLightState& state) override;
-    ndk::ScopedAStatus getLights(std::vector<HwLight>* types) override;
+    ndk::ScopedAStatus getLights(std::vector<HwLight>* lights) override;
 };
 
 }  // namespace light
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 29b31d2..a41f37f 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -90,7 +90,6 @@
         "libneuralnetworks_headers",
     ],
     test_suites: [
-        "general-tests",
         "vts",
     ],
 }
diff --git a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
index 5ffbd43..34bc962 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
@@ -232,26 +232,24 @@
 //     currently 1Mb, which is shared by all transactions in progress
 //     for the process."
 //
-// Will our representation fit under this limit?  There are two complications:
+// Will our representation fit under this limit?  There are three complications:
 // - Our representation size is just approximate (see sizeForBinder()).
-// - This object may not be the only occupant of the Binder transaction buffer.
+// - This object may not be the only occupant of the Binder transaction buffer
+//   (although our VTS test suite should not be putting multiple objects in the
+//   buffer at once).
+// - IBinder.MAX_IPC_SIZE recommends limiting a transaction to 64 * 1024 bytes.
 // So we'll be very conservative: We want the representation size to be no
-// larger than half the transaction buffer size.
+// larger than half the recommended limit.
 //
 // If our representation grows large enough that it still fits within
 // the transaction buffer but combined with other transactions may
 // exceed the buffer size, then we may see intermittent HAL transport
 // errors.
 static bool exceedsBinderSizeLimit(size_t representationSize) {
-    // Instead of using this fixed buffer size, we might instead be able to use
-    // ProcessState::self()->getMmapSize(). However, this has a potential
-    // problem: The binder/mmap size of the current process does not necessarily
-    // indicate the binder/mmap size of the service (i.e., the other process).
-    // The only way it would be a good indication is if both the current process
-    // and the service use the default size.
-    static const size_t kHalfBufferSize = 1024 * 1024 / 2;
+    // There is no C++ API to retrieve the value of the Java variable IBinder.MAX_IPC_SIZE.
+    static const size_t kHalfMaxIPCSize = 64 * 1024 / 2;
 
-    return representationSize > kHalfBufferSize;
+    return representationSize > kHalfMaxIPCSize;
 }
 
 ///////////////////////// VALIDATE EXECUTION ORDER ////////////////////////////
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index e9d4b76..7c1c118 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -58,7 +58,6 @@
         "libneuralnetworks_headers",
     ],
     test_suites: [
-        "general-tests",
         "vts",
     ],
 }
diff --git a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
index 1f4e4ed..dbabbaf 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
@@ -252,26 +252,24 @@
 //     currently 1Mb, which is shared by all transactions in progress
 //     for the process."
 //
-// Will our representation fit under this limit?  There are two complications:
+// Will our representation fit under this limit?  There are three complications:
 // - Our representation size is just approximate (see sizeForBinder()).
-// - This object may not be the only occupant of the Binder transaction buffer.
+// - This object may not be the only occupant of the Binder transaction buffer
+//   (although our VTS test suite should not be putting multiple objects in the
+//   buffer at once).
+// - IBinder.MAX_IPC_SIZE recommends limiting a transaction to 64 * 1024 bytes.
 // So we'll be very conservative: We want the representation size to be no
-// larger than half the transaction buffer size.
+// larger than half the recommended limit.
 //
 // If our representation grows large enough that it still fits within
 // the transaction buffer but combined with other transactions may
 // exceed the buffer size, then we may see intermittent HAL transport
 // errors.
 static bool exceedsBinderSizeLimit(size_t representationSize) {
-    // Instead of using this fixed buffer size, we might instead be able to use
-    // ProcessState::self()->getMmapSize(). However, this has a potential
-    // problem: The binder/mmap size of the current process does not necessarily
-    // indicate the binder/mmap size of the service (i.e., the other process).
-    // The only way it would be a good indication is if both the current process
-    // and the service use the default size.
-    static const size_t kHalfBufferSize = 1024 * 1024 / 2;
+    // There is no C++ API to retrieve the value of the Java variable IBinder.MAX_IPC_SIZE.
+    static const size_t kHalfMaxIPCSize = 64 * 1024 / 2;
 
-    return representationSize > kHalfBufferSize;
+    return representationSize > kHalfMaxIPCSize;
 }
 
 ///////////////////////// VALIDATE EXECUTION ORDER ////////////////////////////
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 2177924..7e4b5bb 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -85,7 +85,6 @@
         "libneuralnetworks_headers",
     ],
     test_suites: [
-        "general-tests",
         "vts",
     ],
 }
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
index 3d783d9..fe38e61 100644
--- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -1262,7 +1262,7 @@
         FILE* pFile = fopen(filename.c_str(), "a");
         uint32_t appendLength = getRandomInt(1, 256);
         for (uint32_t i = 0; i < appendLength; i++) {
-            ASSERT_NE(fputc(getRandomInt<uint8_t>(0, 255), pFile), EOF);
+            ASSERT_NE(fputc(getRandomInt<uint16_t>(0, 255), pFile), EOF);
         }
         fclose(pFile);
         *skip = false;
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index 3375602..d7cd6f5 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -291,26 +291,24 @@
 //     currently 1Mb, which is shared by all transactions in progress
 //     for the process."
 //
-// Will our representation fit under this limit?  There are two complications:
+// Will our representation fit under this limit?  There are three complications:
 // - Our representation size is just approximate (see sizeForBinder()).
-// - This object may not be the only occupant of the Binder transaction buffer.
+// - This object may not be the only occupant of the Binder transaction buffer
+//   (although our VTS test suite should not be putting multiple objects in the
+//   buffer at once).
+// - IBinder.MAX_IPC_SIZE recommends limiting a transaction to 64 * 1024 bytes.
 // So we'll be very conservative: We want the representation size to be no
-// larger than half the transaction buffer size.
+// larger than half the recommended limit.
 //
 // If our representation grows large enough that it still fits within
 // the transaction buffer but combined with other transactions may
 // exceed the buffer size, then we may see intermittent HAL transport
 // errors.
 static bool exceedsBinderSizeLimit(size_t representationSize) {
-    // Instead of using this fixed buffer size, we might instead be able to use
-    // ProcessState::self()->getMmapSize(). However, this has a potential
-    // problem: The binder/mmap size of the current process does not necessarily
-    // indicate the binder/mmap size of the service (i.e., the other process).
-    // The only way it would be a good indication is if both the current process
-    // and the service use the default size.
-    static const size_t kHalfBufferSize = 1024 * 1024 / 2;
+    // There is no C++ API to retrieve the value of the Java variable IBinder.MAX_IPC_SIZE.
+    static const size_t kHalfMaxIPCSize = 64 * 1024 / 2;
 
-    return representationSize > kHalfBufferSize;
+    return representationSize > kHalfMaxIPCSize;
 }
 
 ///////////////////////// VALIDATE EXECUTION ORDER ////////////////////////////
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index 9fa0f0a..07071cc 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -92,7 +92,6 @@
         "libneuralnetworks_headers",
     ],
     test_suites: [
-        "general-tests",
         "vts",
     ],
 }
diff --git a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
index a2013ec..f2cfa3f 100644
--- a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
@@ -1253,7 +1253,7 @@
         FILE* pFile = fopen(filename.c_str(), "a");
         uint32_t appendLength = getRandomInt(1, 256);
         for (uint32_t i = 0; i < appendLength; i++) {
-            ASSERT_NE(fputc(getRandomInt<uint8_t>(0, 255), pFile), EOF);
+            ASSERT_NE(fputc(getRandomInt<uint16_t>(0, 255), pFile), EOF);
         }
         fclose(pFile);
         *skip = false;
diff --git a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
index 849ef7b..d8c7cd1 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
@@ -308,26 +308,24 @@
 //     currently 1Mb, which is shared by all transactions in progress
 //     for the process."
 //
-// Will our representation fit under this limit?  There are two complications:
+// Will our representation fit under this limit?  There are three complications:
 // - Our representation size is just approximate (see sizeForBinder()).
-// - This object may not be the only occupant of the Binder transaction buffer.
+// - This object may not be the only occupant of the Binder transaction buffer
+//   (although our VTS test suite should not be putting multiple objects in the
+//   buffer at once).
+// - IBinder.MAX_IPC_SIZE recommends limiting a transaction to 64 * 1024 bytes.
 // So we'll be very conservative: We want the representation size to be no
-// larger than half the transaction buffer size.
+// larger than half the recommended limit.
 //
 // If our representation grows large enough that it still fits within
 // the transaction buffer but combined with other transactions may
 // exceed the buffer size, then we may see intermittent HAL transport
 // errors.
 static bool exceedsBinderSizeLimit(size_t representationSize) {
-    // Instead of using this fixed buffer size, we might instead be able to use
-    // ProcessState::self()->getMmapSize(). However, this has a potential
-    // problem: The binder/mmap size of the current process does not necessarily
-    // indicate the binder/mmap size of the service (i.e., the other process).
-    // The only way it would be a good indication is if both the current process
-    // and the service use the default size.
-    static const size_t kHalfBufferSize = 1024 * 1024 / 2;
+    // There is no C++ API to retrieve the value of the Java variable IBinder.MAX_IPC_SIZE.
+    static const size_t kHalfMaxIPCSize = 64 * 1024 / 2;
 
-    return representationSize > kHalfBufferSize;
+    return representationSize > kHalfMaxIPCSize;
 }
 
 ///////////////////////// VALIDATE EXECUTION ORDER ////////////////////////////
diff --git a/neuralnetworks/TEST_MAPPING b/neuralnetworks/TEST_MAPPING
index d296828..3218206 100644
--- a/neuralnetworks/TEST_MAPPING
+++ b/neuralnetworks/TEST_MAPPING
@@ -17,54 +17,10 @@
     },
     {
       "name": "neuralnetworks_utils_hal_aidl_test"
-    },
-    {
-      "name": "VtsHalNeuralnetworksV1_0TargetTest",
-      "options": [
-        {
-          // Do not use any sample driver except sample-all in order to reduce
-          // testing time. The other sample drivers (fast-float, quant, etc.)
-          // are subsets of sample-all.
-          "include-filter": "-*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*"
-        }
-      ]
-    },
-    {
-      "name": "VtsHalNeuralnetworksV1_1TargetTest",
-      "options": [
-        {
-          // Do not use any sample driver except sample-all in order to reduce
-          // testing time. The other sample drivers (fast-float, quant, etc.)
-          // are subsets of sample-all.
-          "include-filter": "-*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*"
-        }
-      ]
     }
   ],
   "presubmit-large": [
     {
-      "name": "VtsHalNeuralnetworksV1_2TargetTest",
-      "options": [
-        {
-          // Do not use any sample driver except sample-all in order to reduce
-          // testing time. The other sample drivers (fast-float, quant, etc.)
-          // are subsets of sample-all.
-          "include-filter": "-*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*"
-        }
-      ]
-    },
-    {
-      "name": "VtsHalNeuralnetworksV1_3TargetTest",
-      "options": [
-        {
-          // Do not use any sample driver except sample-all in order to reduce
-          // testing time. The other sample drivers (fast-float, quant, etc.)
-          // are subsets of sample-all.
-          "include-filter": "-*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*"
-        }
-      ]
-    },
-    {
       "name": "VtsHalNeuralnetworksTargetTest",
       "options": [
         {
diff --git a/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
index 7451f7e..da0fe64 100644
--- a/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
@@ -1068,7 +1068,7 @@
         FILE* pFile = fopen(filename.c_str(), "a");
         uint32_t appendLength = getRandomInt(1, 256);
         for (uint32_t i = 0; i < appendLength; i++) {
-            ASSERT_NE(fputc(getRandomInt<uint8_t>(0, 255), pFile), EOF);
+            ASSERT_NE(fputc(getRandomInt<uint16_t>(0, 255), pFile), EOF);
         }
         fclose(pFile);
         *skip = false;
diff --git a/neuralnetworks/aidl/vts/functional/ValidateModel.cpp b/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
index 060434e..d7baf19 100644
--- a/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
@@ -344,26 +344,24 @@
 //     currently 1Mb, which is shared by all transactions in progress
 //     for the process."
 //
-// Will our representation fit under this limit?  There are two complications:
+// Will our representation fit under this limit?  There are three complications:
 // - Our representation size is just approximate (see sizeForBinder()).
-// - This object may not be the only occupant of the Binder transaction buffer.
+// - This object may not be the only occupant of the Binder transaction buffer
+//   (although our VTS test suite should not be putting multiple objects in the
+//   buffer at once).
+// - IBinder.MAX_IPC_SIZE recommends limiting a transaction to 64 * 1024 bytes.
 // So we'll be very conservative: We want the representation size to be no
-// larger than half the transaction buffer size.
+// larger than half the recommended limit.
 //
 // If our representation grows large enough that it still fits within
 // the transaction buffer but combined with other transactions may
 // exceed the buffer size, then we may see intermittent HAL transport
 // errors.
 static bool exceedsBinderSizeLimit(size_t representationSize) {
-    // Instead of using this fixed buffer size, we might instead be able to use
-    // ProcessState::self()->getMmapSize(). However, this has a potential
-    // problem: The binder/mmap size of the current process does not necessarily
-    // indicate the binder/mmap size of the service (i.e., the other process).
-    // The only way it would be a good indication is if both the current process
-    // and the service use the default size.
-    static const size_t kHalfBufferSize = 1024 * 1024 / 2;
+    // There is no C++ API to retrieve the value of the Java variable IBinder.MAX_IPC_SIZE.
+    static const size_t kHalfMaxIPCSize = 64 * 1024 / 2;
 
-    return representationSize > kHalfBufferSize;
+    return representationSize > kHalfMaxIPCSize;
 }
 
 ///////////////////////// VALIDATE EXECUTION ORDER ////////////////////////////
diff --git a/nfc/aidl/Android.bp b/nfc/aidl/Android.bp
index b9578f4..09a45d1 100644
--- a/nfc/aidl/Android.bp
+++ b/nfc/aidl/Android.bp
@@ -34,11 +34,6 @@
             sdk_version: "module_current",
             enabled: false,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/oemlock/aidl/Android.bp b/oemlock/aidl/Android.bp
index d1930f9..1c19bb1 100644
--- a/oemlock/aidl/Android.bp
+++ b/oemlock/aidl/Android.bp
@@ -16,11 +16,6 @@
         java: {
             platform_apis: true,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions: ["1"],
 }
diff --git a/power/OWNERS b/power/OWNERS
new file mode 100644
index 0000000..7229b22
--- /dev/null
+++ b/power/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 826709
+
+# ADPF virtual team
+lpy@google.com
+wvw@google.com
diff --git a/power/TEST_MAPPING b/power/TEST_MAPPING
new file mode 100644
index 0000000..c0963f9
--- /dev/null
+++ b/power/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "VtsHalPowerTargetTest"
+    }
+  ]
+}
diff --git a/power/aidl/Android.bp b/power/aidl/Android.bp
index e4708f8..70b1203 100644
--- a/power/aidl/Android.bp
+++ b/power/aidl/Android.bp
@@ -35,11 +35,6 @@
         java: {
             platform_apis: true,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp
index 223b9d5..b321394 100644
--- a/power/aidl/default/Android.bp
+++ b/power/aidl/default/Android.bp
@@ -35,6 +35,7 @@
     srcs: [
         "main.cpp",
         "Power.cpp",
+        "PowerHintSession.cpp",
     ],
 }
 
diff --git a/power/aidl/default/Power.cpp b/power/aidl/default/Power.cpp
index 7f08f44..8fe370c 100644
--- a/power/aidl/default/Power.cpp
+++ b/power/aidl/default/Power.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "Power.h"
+#include "PowerHintSession.h"
 
 #include <android-base/logging.h>
 
@@ -25,42 +26,53 @@
 namespace impl {
 namespace example {
 
+using namespace std::chrono_literals;
+
+using ndk::ScopedAStatus;
+
 const std::vector<Boost> BOOST_RANGE{ndk::enum_range<Boost>().begin(),
                                      ndk::enum_range<Boost>().end()};
 const std::vector<Mode> MODE_RANGE{ndk::enum_range<Mode>().begin(), ndk::enum_range<Mode>().end()};
 
-ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {
+ScopedAStatus Power::setMode(Mode type, bool enabled) {
     LOG(VERBOSE) << "Power setMode: " << static_cast<int32_t>(type) << " to: " << enabled;
-    return ndk::ScopedAStatus::ok();
+    return ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Power::isModeSupported(Mode type, bool* _aidl_return) {
+ScopedAStatus Power::isModeSupported(Mode type, bool* _aidl_return) {
     LOG(INFO) << "Power isModeSupported: " << static_cast<int32_t>(type);
     *_aidl_return = type >= MODE_RANGE.front() && type <= MODE_RANGE.back();
-    return ndk::ScopedAStatus::ok();
+    return ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) {
+ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) {
     LOG(VERBOSE) << "Power setBoost: " << static_cast<int32_t>(type)
                  << ", duration: " << durationMs;
-    return ndk::ScopedAStatus::ok();
+    return ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Power::isBoostSupported(Boost type, bool* _aidl_return) {
+ScopedAStatus Power::isBoostSupported(Boost type, bool* _aidl_return) {
     LOG(INFO) << "Power isBoostSupported: " << static_cast<int32_t>(type);
     *_aidl_return = type >= BOOST_RANGE.front() && type <= BOOST_RANGE.back();
-    return ndk::ScopedAStatus::ok();
+    return ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Power::createHintSession(int32_t, int32_t, const std::vector<int32_t>&, int64_t,
-                                            std::shared_ptr<IPowerHintSession>* _aidl_return) {
-    *_aidl_return = nullptr;
-    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ScopedAStatus Power::createHintSession(int32_t, int32_t, const std::vector<int32_t>& tids, int64_t,
+                                       std::shared_ptr<IPowerHintSession>* _aidl_return) {
+    if (tids.size() == 0) {
+        *_aidl_return = nullptr;
+        return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    std::shared_ptr<IPowerHintSession> powerHintSession =
+            ndk::SharedRefBase::make<PowerHintSession>();
+    mPowerHintSessions.push_back(powerHintSession);
+    *_aidl_return = powerHintSession;
+    return ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Power::getHintSessionPreferredRate(int64_t* outNanoseconds) {
-    *outNanoseconds = -1;
-    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ScopedAStatus Power::getHintSessionPreferredRate(int64_t* outNanoseconds) {
+    *outNanoseconds = std::chrono::nanoseconds(1ms).count();
+    return ScopedAStatus::ok();
 }
 
 }  // namespace example
diff --git a/power/aidl/default/Power.h b/power/aidl/default/Power.h
index ef6439d..7f8405e 100644
--- a/power/aidl/default/Power.h
+++ b/power/aidl/default/Power.h
@@ -26,6 +26,7 @@
 namespace example {
 
 class Power : public BnPower {
+  public:
     ndk::ScopedAStatus setMode(Mode type, bool enabled) override;
     ndk::ScopedAStatus isModeSupported(Mode type, bool* _aidl_return) override;
     ndk::ScopedAStatus setBoost(Boost type, int32_t durationMs) override;
@@ -35,6 +36,9 @@
                                          int64_t durationNanos,
                                          std::shared_ptr<IPowerHintSession>* _aidl_return) override;
     ndk::ScopedAStatus getHintSessionPreferredRate(int64_t* outNanoseconds) override;
+
+  private:
+    std::vector<std::shared_ptr<IPowerHintSession>> mPowerHintSessions;
 };
 
 }  // namespace example
diff --git a/power/aidl/default/PowerHintSession.cpp b/power/aidl/default/PowerHintSession.cpp
new file mode 100644
index 0000000..17fd26a
--- /dev/null
+++ b/power/aidl/default/PowerHintSession.cpp
@@ -0,0 +1,50 @@
+/*
+ * 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 "PowerHintSession.h"
+
+#include <android-base/logging.h>
+
+namespace aidl::android::hardware::power::impl::example {
+
+using ndk::ScopedAStatus;
+
+PowerHintSession::PowerHintSession() {}
+
+ScopedAStatus PowerHintSession::updateTargetWorkDuration(int64_t targetDurationNanos) {
+    LOG(VERBOSE) << __func__ << "target duration in nanoseconds: " << targetDurationNanos;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus PowerHintSession::reportActualWorkDuration(
+        const std::vector<WorkDuration>& /* durations */) {
+    LOG(VERBOSE) << __func__;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus PowerHintSession::pause() {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus PowerHintSession::resume() {
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus PowerHintSession::close() {
+    return ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/default/PowerHintSession.h b/power/aidl/default/PowerHintSession.h
new file mode 100644
index 0000000..b7bf54c
--- /dev/null
+++ b/power/aidl/default/PowerHintSession.h
@@ -0,0 +1,35 @@
+/*
+ * 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 <aidl/android/hardware/power/BnPowerHintSession.h>
+#include <aidl/android/hardware/power/WorkDuration.h>
+
+namespace aidl::android::hardware::power::impl::example {
+
+class PowerHintSession : public BnPowerHintSession {
+  public:
+    explicit PowerHintSession();
+    ndk::ScopedAStatus updateTargetWorkDuration(int64_t targetDurationNanos) override;
+    ndk::ScopedAStatus reportActualWorkDuration(
+            const std::vector<WorkDuration>& durations) override;
+    ndk::ScopedAStatus pause() override;
+    ndk::ScopedAStatus resume() override;
+    ndk::ScopedAStatus close() override;
+};
+
+}  // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/vts/Android.bp b/power/aidl/vts/Android.bp
index ea398ac..4e8f517 100644
--- a/power/aidl/vts/Android.bp
+++ b/power/aidl/vts/Android.bp
@@ -35,6 +35,7 @@
         "android.hardware.power-V3-ndk",
     ],
     test_suites: [
+        "general-tests",
         "vts",
     ],
 }
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index 2cfa04a..b81dd8f 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -83,6 +83,14 @@
         DurationWrapper(1000000000L, 4L),
 };
 
+// DEVICEs launching with Android 11 MUST meet the requirements for the
+// target-level=5 compatibility_matrix file.
+const uint64_t kCompatibilityMatrix5ApiLevel = 30;
+
+// DEVICEs launching with Android 13 MUST meet the requirements for the
+// target-level=7 compatibility_matrix file.
+const uint64_t kCompatibilityMatrix7ApiLevel = 33;
+
 inline bool isUnknownOrUnsupported(const ndk::ScopedAStatus& status) {
     return status.getStatus() == STATUS_UNKNOWN_TRANSACTION ||
            status.getExceptionCode() == EX_UNSUPPORTED_OPERATION;
@@ -94,9 +102,13 @@
         AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
         ASSERT_NE(binder, nullptr);
         power = IPower::fromBinder(ndk::SpAIBinder(binder));
+
+        mApiLevel = GetUintProperty<uint64_t>("ro.vendor.api_level", 0);
+        ASSERT_NE(mApiLevel, 0);
     }
 
     std::shared_ptr<IPower> power;
+    uint64_t mApiLevel;
 };
 
 TEST_P(PowerAidl, setMode) {
@@ -152,11 +164,11 @@
 TEST_P(PowerAidl, getHintSessionPreferredRate) {
     int64_t rate = -1;
     auto status = power->getHintSessionPreferredRate(&rate);
-    if (!status.isOk()) {
+    if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
         EXPECT_TRUE(isUnknownOrUnsupported(status));
-        return;
+        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
     }
-
+    ASSERT_TRUE(status.isOk());
     // At least 1ms rate limit from HAL
     ASSERT_GE(rate, 1000000);
 }
@@ -164,10 +176,11 @@
 TEST_P(PowerAidl, createAndCloseHintSession) {
     std::shared_ptr<IPowerHintSession> session;
     auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
-    if (!status.isOk()) {
+    if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
         EXPECT_TRUE(isUnknownOrUnsupported(status));
-        return;
+        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
     }
+    ASSERT_TRUE(status.isOk());
     ASSERT_NE(nullptr, session);
     ASSERT_TRUE(session->pause().isOk());
     ASSERT_TRUE(session->resume().isOk());
@@ -175,12 +188,18 @@
     ASSERT_TRUE(session->close().isOk());
     session.reset();
 }
+
 TEST_P(PowerAidl, createHintSessionFailed) {
     std::shared_ptr<IPowerHintSession> session;
     auto status = power->createHintSession(getpid(), getuid(), kEmptyTids, 16666666L, &session);
+
+    // Regardless of whether V2 and beyond is supported, the status is always not STATUS_OK.
     ASSERT_FALSE(status.isOk());
-    if (isUnknownOrUnsupported(status)) {
-        return;
+
+    // If device not launching with Android 13 and beyond, check whether it's supported,
+    // if not, skip the test.
+    if (mApiLevel < kCompatibilityMatrix7ApiLevel && isUnknownOrUnsupported(status)) {
+        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
     }
     ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
 }
@@ -188,10 +207,11 @@
 TEST_P(PowerAidl, updateAndReportDurations) {
     std::shared_ptr<IPowerHintSession> session;
     auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
-    if (!status.isOk()) {
+    if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
         EXPECT_TRUE(isUnknownOrUnsupported(status));
-        return;
+        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
     }
+    ASSERT_TRUE(status.isOk());
     ASSERT_NE(nullptr, session);
 
     ASSERT_TRUE(session->updateTargetWorkDuration(16666667LL).isOk());
@@ -201,14 +221,13 @@
 // FIXED_PERFORMANCE mode is required for all devices which ship on Android 11
 // or later
 TEST_P(PowerAidl, hasFixedPerformance) {
-    auto apiLevel = GetUintProperty<uint64_t>("ro.vendor.api_level", 0);
-    ASSERT_NE(apiLevel, 0);
-
-    if (apiLevel >= 30) {
-        bool supported;
-        ASSERT_TRUE(power->isModeSupported(Mode::FIXED_PERFORMANCE, &supported).isOk());
-        ASSERT_TRUE(supported);
+    if (mApiLevel < kCompatibilityMatrix5ApiLevel) {
+        GTEST_SKIP() << "FIXED_PERFORMANCE mode is only required for all devices launching Android "
+                        "11 or later.";
     }
+    bool supported;
+    ASSERT_TRUE(power->isModeSupported(Mode::FIXED_PERFORMANCE, &supported).isOk());
+    ASSERT_TRUE(supported);
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerAidl);
diff --git a/power/stats/aidl/Android.bp b/power/stats/aidl/Android.bp
index 48d3c51..b1b2515 100644
--- a/power/stats/aidl/Android.bp
+++ b/power/stats/aidl/Android.bp
@@ -32,11 +32,6 @@
         java: {
             platform_apis: true,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
         cpp: {
             enabled: true,
         },
diff --git a/radio/1.0/Android.bp b/radio/1.0/Android.bp
index 8d0d782..e49a50d 100644
--- a/radio/1.0/Android.bp
+++ b/radio/1.0/Android.bp
@@ -25,7 +25,7 @@
     ],
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
     ],
     gen_java: true,
 }
diff --git a/radio/aidl/Android.bp b/radio/aidl/Android.bp
index 72f160d..98eafc1 100644
--- a/radio/aidl/Android.bp
+++ b/radio/aidl/Android.bp
@@ -20,11 +20,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
@@ -49,11 +44,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
@@ -78,11 +68,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
@@ -107,11 +92,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
@@ -136,11 +116,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
@@ -165,11 +140,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
@@ -197,11 +167,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
@@ -229,11 +194,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/radio/aidl/OWNERS b/radio/aidl/OWNERS
new file mode 100644
index 0000000..7b01aad
--- /dev/null
+++ b/radio/aidl/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 20868
+include ../1.0/vts/OWNERS
+
diff --git a/radio/aidl/compat/libradiocompat/data/structs.cpp b/radio/aidl/compat/libradiocompat/data/structs.cpp
index 4ff89a1..cc6dcbc 100644
--- a/radio/aidl/compat/libradiocompat/data/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/data/structs.cpp
@@ -28,14 +28,14 @@
 
 V1_5::DataProfileInfo toHidl(const aidl::DataProfileInfo& info) {
     return {
-            .profileId = V1_0::DataProfileId{info.profileId},
+            .profileId = static_cast<V1_0::DataProfileId>(info.profileId),
             .apn = info.apn,
-            .protocol = V1_4::PdpProtocolType{info.protocol},
-            .roamingProtocol = V1_4::PdpProtocolType{info.roamingProtocol},
-            .authType = V1_0::ApnAuthType{info.authType},
+            .protocol = static_cast<V1_4::PdpProtocolType>(info.protocol),
+            .roamingProtocol = static_cast<V1_4::PdpProtocolType>(info.roamingProtocol),
+            .authType = static_cast<V1_0::ApnAuthType>(info.authType),
             .user = info.user,
             .password = info.password,
-            .type = V1_0::DataProfileInfoType{info.type},
+            .type = static_cast<V1_0::DataProfileInfoType>(info.type),
             .maxConnsTime = info.maxConnsTime,
             .maxConns = info.maxConns,
             .waitTime = info.waitTime,
@@ -74,7 +74,7 @@
             .sliceDifferentiator = info.sliceDifferentiator,
             .mappedHplmnSst = static_cast<V1_6::SliceServiceType>(info.mappedHplmnSst),
             .mappedHplmnSD = info.mappedHplmnSd,
-            .status = V1_6::SliceStatus{info.status},
+            .status = static_cast<V1_6::SliceStatus>(info.status),
     };
 }
 
@@ -106,7 +106,7 @@
 
 V1_1::KeepaliveRequest toHidl(const aidl::KeepaliveRequest& keep) {
     return {
-            .type = V1_1::KeepaliveType{keep.type},
+            .type = static_cast<V1_1::KeepaliveType>(keep.type),
             .sourceAddress = keep.sourceAddress,
             .sourcePort = keep.sourcePort,
             .destinationAddress = keep.destinationAddress,
diff --git a/radio/aidl/compat/libradiocompat/messaging/structs.cpp b/radio/aidl/compat/libradiocompat/messaging/structs.cpp
index 9019680..f30c5ce 100644
--- a/radio/aidl/compat/libradiocompat/messaging/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/messaging/structs.cpp
@@ -45,11 +45,11 @@
 
 static V1_0::CdmaSmsAddress toHidl(const aidl::CdmaSmsAddress& addr) {
     return {
-            .digitMode = V1_0::CdmaSmsDigitMode{addr.digitMode},
+            .digitMode = static_cast<V1_0::CdmaSmsDigitMode>(addr.digitMode),
             .numberMode = addr.isNumberModeDataNetwork ? V1_0::CdmaSmsNumberMode::DATA_NETWORK
                                                        : V1_0::CdmaSmsNumberMode::NOT_DATA_NETWORK,
-            .numberType = V1_0::CdmaSmsNumberType{addr.numberType},
-            .numberPlan = V1_0::CdmaSmsNumberPlan{addr.numberPlan},
+            .numberType = static_cast<V1_0::CdmaSmsNumberType>(addr.numberType),
+            .numberPlan = static_cast<V1_0::CdmaSmsNumberPlan>(addr.numberPlan),
             .digits = addr.digits,
     };
 }
@@ -64,7 +64,7 @@
 
 static V1_0::CdmaSmsSubaddress toHidl(const aidl::CdmaSmsSubaddress& addr) {
     return {
-            .subaddressType = V1_0::CdmaSmsSubaddressType{addr.subaddressType},
+            .subaddressType = static_cast<V1_0::CdmaSmsSubaddressType>(addr.subaddressType),
             .odd = addr.odd,
             .digits = addr.digits,
     };
@@ -94,7 +94,7 @@
 
 V1_0::ImsSmsMessage toHidl(const aidl::ImsSmsMessage& msg) {
     return {
-            .tech = V1_0::RadioTechnologyFamily{msg.tech},
+            .tech = static_cast<V1_0::RadioTechnologyFamily>(msg.tech),
             .retry = msg.retry,
             .messageRef = msg.messageRef,
             .cdmaMessage = toHidl(msg.cdmaMessage),
@@ -147,14 +147,14 @@
 
 V1_0::CdmaSmsWriteArgs toHidl(const aidl::CdmaSmsWriteArgs& args) {
     return {
-            .status = V1_0::CdmaSmsWriteArgsStatus{args.status},
+            .status = static_cast<V1_0::CdmaSmsWriteArgsStatus>(args.status),
             .message = toHidl(args.message),
     };
 }
 
 V1_0::SmsWriteArgs toHidl(const aidl::SmsWriteArgs& args) {
     return {
-            .status = V1_0::SmsWriteArgsStatus{args.status},
+            .status = static_cast<V1_0::SmsWriteArgsStatus>(args.status),
             .pdu = args.pdu,
             .smsc = args.smsc,
     };
diff --git a/radio/aidl/compat/libradiocompat/modem/structs.cpp b/radio/aidl/compat/libradiocompat/modem/structs.cpp
index 69e651b..6f32cdf 100644
--- a/radio/aidl/compat/libradiocompat/modem/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/modem/structs.cpp
@@ -30,7 +30,7 @@
 
 V1_0::NvWriteItem toHidl(const aidl::NvWriteItem& item) {
     return {
-            .itemId = V1_0::NvItem{item.itemId},
+            .itemId = static_cast<V1_0::NvItem>(item.itemId),
             .value = item.value,
     };
 }
@@ -48,10 +48,10 @@
 V1_0::RadioCapability toHidl(const aidl::RadioCapability& capa) {
     return {
             .session = capa.session,
-            .phase = V1_0::RadioCapabilityPhase{capa.phase},
+            .phase = static_cast<V1_0::RadioCapabilityPhase>(capa.phase),
             .raf = toHidlBitfield<V1_0::RadioAccessFamily>(capa.raf),
             .logicalModemUuid = capa.logicalModemUuid,
-            .status = V1_0::RadioCapabilityStatus{capa.status},
+            .status = static_cast<V1_0::RadioCapabilityStatus>(capa.status),
     };
 }
 
diff --git a/radio/aidl/compat/libradiocompat/network/structs.cpp b/radio/aidl/compat/libradiocompat/network/structs.cpp
index d0b3b90..30d4f6d 100644
--- a/radio/aidl/compat/libradiocompat/network/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/network/structs.cpp
@@ -66,7 +66,7 @@
 
 V1_5::SignalThresholdInfo toHidl(const aidl::SignalThresholdInfo& info) {
     return {
-            .signalMeasurement = V1_5::SignalMeasurementType{info.signalMeasurement},
+            .signalMeasurement = static_cast<V1_5::SignalMeasurementType>(info.signalMeasurement),
             .hysteresisMs = info.hysteresisMs,
             .hysteresisDb = info.hysteresisDb,
             .thresholds = info.thresholds,
@@ -155,7 +155,7 @@
 
 V1_5::NetworkScanRequest toHidl(const aidl::NetworkScanRequest& req) {
     return {
-            .type = V1_1::ScanType{req.type},
+            .type = static_cast<V1_1::ScanType>(req.type),
             .interval = req.interval,
             .specifiers = toHidl(req.specifiers),
             .maxSearchTime = req.maxSearchTime,
diff --git a/radio/aidl/compat/libradiocompat/sim/structs.cpp b/radio/aidl/compat/libradiocompat/sim/structs.cpp
index bfbff02..00db2b8 100644
--- a/radio/aidl/compat/libradiocompat/sim/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/sim/structs.cpp
@@ -65,7 +65,7 @@
     return {
             .mcc = carrier.mcc,
             .mnc = carrier.mnc,
-            .matchType = V1_0::CarrierMatchType{carrier.matchType},
+            .matchType = static_cast<V1_0::CarrierMatchType>(carrier.matchType),
             .matchData = carrier.matchData,
     };
 }
@@ -107,7 +107,7 @@
 V1_6::ImsiEncryptionInfo toHidl_1_6(const aidl::ImsiEncryptionInfo& info) {
     return {
             .base = toHidl(info),
-            .keyType = V1_6::PublicKeyType{info.keyType},
+            .keyType = static_cast<V1_6::PublicKeyType>(info.keyType),
     };
 }
 
diff --git a/radio/aidl/compat/libradiocompat/voice/structs.cpp b/radio/aidl/compat/libradiocompat/voice/structs.cpp
index 254ea20..35c8d46 100644
--- a/radio/aidl/compat/libradiocompat/voice/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/voice/structs.cpp
@@ -29,15 +29,15 @@
 V1_0::Dial toHidl(const aidl::Dial& info) {
     return {
             .address = info.address,
-            .clir = V1_0::Clir{info.clir},
+            .clir = static_cast<V1_0::Clir>(info.clir),
             .uusInfo = toHidl(info.uusInfo),
     };
 }
 
 V1_0::UusInfo toHidl(const aidl::UusInfo& info) {
     return {
-            .uusType = V1_0::UusType{info.uusType},
-            .uusDcs = V1_0::UusDcs{info.uusDcs},
+            .uusType = static_cast<V1_0::UusType>(info.uusType),
+            .uusDcs = static_cast<V1_0::UusDcs>(info.uusDcs),
             .uusData = info.uusData,
     };
 }
@@ -55,7 +55,7 @@
 
 V1_0::CallForwardInfo toHidl(const aidl::CallForwardInfo& info) {
     return {
-            .status = V1_0::CallForwardInfoStatus{info.status},
+            .status = static_cast<V1_0::CallForwardInfoStatus>(info.status),
             .reason = info.reason,
             .serviceClass = info.serviceClass,
             .toa = info.toa,
diff --git a/radio/aidl/vts/OWNERS b/radio/aidl/vts/OWNERS
deleted file mode 100644
index e75c6c8..0000000
--- a/radio/aidl/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 20868
-include ../../1.0/vts/OWNERS
-
diff --git a/rebootescrow/aidl/Android.bp b/rebootescrow/aidl/Android.bp
index c764f86..39aaa07 100644
--- a/rebootescrow/aidl/Android.bp
+++ b/rebootescrow/aidl/Android.bp
@@ -18,11 +18,6 @@
         java: {
             platform_apis: true,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions: ["1"],
 }
diff --git a/security/OWNERS b/security/OWNERS
index 54d820a..fbaf854 100644
--- a/security/OWNERS
+++ b/security/OWNERS
@@ -1,5 +1,14 @@
+# Bug component: 1084733
+
+# Please assign all bugs related to /hardware/interfaces/security/ to the team alias:
+#
+#    android-hardware-security@google.com
+#
+# This will get them auto-assigned to the on-call triage engineer, ensuring quickest response.
+
 drysdale@google.com
+eranm@google.com
+hasinitg@google.com
 jbires@google.com
-jdanis@google.com
-seleneh@google.com
 swillden@google.com
+zeuthen@google.com
diff --git a/security/dice/aidl/Android.bp b/security/dice/aidl/Android.bp
index 97781b3..5625d70 100644
--- a/security/dice/aidl/Android.bp
+++ b/security/dice/aidl/Android.bp
@@ -34,9 +34,6 @@
             platform_apis: false,
         },
         ndk: {
-            vndk: {
-                enabled: true,
-            },
             apps_enabled: false,
             apex_available: [
                 "//apex_available:platform",
diff --git a/security/keymint/RKP_CHANGELOG.md b/security/keymint/RKP_CHANGELOG.md
new file mode 100644
index 0000000..243fc26
--- /dev/null
+++ b/security/keymint/RKP_CHANGELOG.md
@@ -0,0 +1,33 @@
+# Remote Provisioning Changelog
+
+This document provides an exact description of which changes have occurred in the
+`IRemotelyProvisionedComponent` HAL interface in each Android release.
+
+## Releases
+* **Android S (12):** IRemotelyProvisionedComponent v1
+* **Android T (13):** IRemotelyProvisionedComponent v2
+* **Android U (14):** IRemotelyProvisionedComponent v3
+
+## IRemotelyProvisionedComponent 1 -> 2
+* DeviceInfo
+  * Most entries are no longer optional.
+  * `att_id_state` is now `fused`. `fused` is used to indicate if SecureBoot is enabled.
+  * `version` is now `2`.
+  * `board` has been removed.
+  * `device` has been added.
+* RpcHardwareInfo
+  * `uniqueId` String added as a field in order to differentiate IRPC instances on device.
+
+## IRemotelyProvisionedComponent 2 -> 3
+* ProtectedData has been removed.
+* DeviceInfo
+  * `version` has moved to a top-level field within the CSR generated by the HAL
+* IRemotelyProvisionedComponent
+  * The need for an EEK has been removed. There is no longer an encrypted portion of the CSR.
+  * Test mode has been removed.
+  * The schema for the CSR itself has been significantly simplified, please see
+    IRemotelyProvisionedComponent.aidl for more details. Notably,
+    * the chain of signing, MACing, and encryption operations has been replaced with a single
+      COSE_Sign1 object.
+    * CertificateType has been added to identify the type of certificate being requested.
+
diff --git a/security/keymint/aidl/Android.bp b/security/keymint/aidl/Android.bp
index a233087..6efff2f 100644
--- a/security/keymint/aidl/Android.bp
+++ b/security/keymint/aidl/Android.bp
@@ -22,9 +22,6 @@
             platform_apis: true,
         },
         ndk: {
-            vndk: {
-                enabled: true,
-            },
             apps_enabled: false,
         },
         rust: {
@@ -55,21 +52,21 @@
 cc_defaults {
     name: "keymint_use_latest_hal_aidl_ndk_static",
     static_libs: [
-        "android.hardware.security.keymint-V2-ndk",
+        "android.hardware.security.keymint-V3-ndk",
     ],
 }
 
 cc_defaults {
     name: "keymint_use_latest_hal_aidl_ndk_shared",
     shared_libs: [
-        "android.hardware.security.keymint-V2-ndk",
+        "android.hardware.security.keymint-V3-ndk",
     ],
 }
 
 cc_defaults {
     name: "keymint_use_latest_hal_aidl_cpp_static",
     static_libs: [
-        "android.hardware.security.keymint-V2-cpp",
+        "android.hardware.security.keymint-V3-cpp",
     ],
 }
 
@@ -79,6 +76,6 @@
 rust_defaults {
     name: "keymint_use_latest_hal_aidl_rust",
     rustlibs: [
-        "android.hardware.security.keymint-V2-rust",
+        "android.hardware.security.keymint-V3-rust",
     ],
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index f566462..626ece8 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -38,9 +38,11 @@
   android.hardware.security.keymint.RpcHardwareInfo getHardwareInfo();
   byte[] generateEcdsaP256KeyPair(in boolean testMode, out android.hardware.security.keymint.MacedPublicKey macedPublicKey);
   byte[] generateCertificateRequest(in boolean testMode, in android.hardware.security.keymint.MacedPublicKey[] keysToSign, in byte[] endpointEncryptionCertChain, in byte[] challenge, out android.hardware.security.keymint.DeviceInfo deviceInfo, out android.hardware.security.keymint.ProtectedData protectedData);
+  byte[] generateCertificateRequestV2(in android.hardware.security.keymint.MacedPublicKey[] keysToSign, in byte[] challenge);
   const int STATUS_FAILED = 1;
   const int STATUS_INVALID_MAC = 2;
   const int STATUS_PRODUCTION_KEY_IN_TEST_REQUEST = 3;
   const int STATUS_TEST_KEY_IN_PRODUCTION_REQUEST = 4;
   const int STATUS_INVALID_EEK = 5;
+  const int STATUS_REMOVED = 6;
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
index abb2a7b..f0af619 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -37,19 +37,18 @@
      *         "product" : tstr,
      *         "model" : tstr,
      *         "device" : tstr,
-     *         "vb_state" : "green" / "yellow" / "orange",    // Taken from the AVB values
-     *         "bootloader_state" : "locked" / "unlocked",    // Taken from the AVB values
-     *         "vbmeta_digest": bstr,                         // Taken from the AVB values
-     *         ? "os_version" : tstr,                         // Same as
-     *                                                        // android.os.Build.VERSION.release
-     *                                                        // Not optional for TEE.
-     *         "system_patch_level" : uint,                   // YYYYMMDD
-     *         "boot_patch_level" : uint,                     // YYYYMMDD
-     *         "vendor_patch_level" : uint,                   // YYYYMMDD
-     *         "version" : 2,                                 // The CDDL schema version.
+     *         "vb_state" : "green" / "yellow" / "orange",    ; Taken from the AVB values
+     *         "bootloader_state" : "locked" / "unlocked",    ; Taken from the AVB values
+     *         "vbmeta_digest": bstr,                         ; Taken from the AVB values
+     *         ? "os_version" : tstr,                         ; Same as
+     *                                                        ; android.os.Build.VERSION.release
+     *                                                        ; Not optional for TEE.
+     *         "system_patch_level" : uint,                   ; YYYYMMDD
+     *         "boot_patch_level" : uint,                     ; YYYYMMDD
+     *         "vendor_patch_level" : uint,                   ; YYYYMMDD
      *         "security_level" : "tee" / "strongbox",
-     *         "fused": 1 / 0,  // 1 if secure boot is enforced for the processor that the IRPC
-     *                          // implementation is contained in. 0 otherwise.
+     *         "fused": 1 / 0,  ; 1 if secure boot is enforced for the processor that the IRPC
+     *                          ; implementation is contained in. 0 otherwise.
      *     }
      */
     byte[] deviceInfo;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 95a3710..2e4fc15 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -196,12 +196,12 @@
  * derive a key that is used to encrypt the private/secret key material.
  *
  * The root of trust consists of a bitstring that must be derived from the public key used by
- * Verified Boot to verify the signature on the boot image and from the lock state of the
- * device.  If the public key is changed to allow a different system image to be used or if the
- * lock state is changed, then all of the IKeyMintDevice-protected keys created by the previous
- * system state must be unusable, unless the previous state is restored.  The goal is to increase
- * the value of the software-enforced key access controls by making it impossible for an attacker-
- * installed operating system to use IKeyMintDevice keys.
+ * Verified Boot to verify the signature on the boot image, from the lock state and from the
+ * Verified Boot state of the device.  If the public key is changed to allow a different system
+ * image to be used or if the lock state is changed, then all of the IKeyMintDevice-protected keys
+ * created by the previous system state must be unusable, unless the previous state is restored.
+ * The goal is to increase the value of the software-enforced key access controls by making it
+ * impossible for an attacker-installed operating system to use IKeyMintDevice keys.
  *
  * == Version Binding ==
  *
@@ -336,6 +336,17 @@
      * Only Tag::KEY_SIZE is required to generate an 3DES key, and its value must be 168.  If
      * omitted, generateKey must return ErrorCode::UNSUPPORTED_KEY_SIZE.
      *
+     * == HMAC Keys ==
+     *
+     * Tag::KEY_SIZE must be provided to generate an HMAC key, and its value must be >= 64 and a
+     * multiple of 8.  All devices must support key sizes up to 512 bits, but StrongBox devices must
+     * not support key sizes larger than 512 bits.  If omitted or invalid, generateKey() must return
+     * ErrorCode::UNSUPPORTED_KEY_SIZE.
+     *
+     * Tag::MIN_MAC_LENGTH must be provided, and must be a multiple of 8 in the range 64 to 512
+     * bits (inclusive). If omitted, generateKey must return ErrorCode::MISSING_MIN_MAC_LENGTH; if
+     * invalid, generateKey must return ErrorCode::UNSUPPORTED_MIN_MAC_LENGTH.
+     *
      * @param keyParams Key generation parameters are defined as KeyMintDevice tag/value pairs,
      *        provided in params.  See above for detailed specifications of which tags are required
      *        for which types of keys.
@@ -613,9 +624,15 @@
      *
      *   o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
      *
-     *   o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be less than
-     *     the current secure timestamp (which is a monotonic timer counting milliseconds since
-     *     boot.)
+     *   o If the device has a source of secure time, then the timestamp in the auth token plus the
+     *     value of the Tag::AUTH_TIMEOUT must be greater than the current secure timestamp (which
+     *     is a monotonic timer counting milliseconds since boot).
+     *
+     *   o If the device does not have a source of secure time, then the timestamp check should be
+     *     performed on the first update(), updateAad() or finish() invocation for the operation,
+     *     using the timeStampToken parameter provided on the invocation to indicate the current
+     *     timestamp. It may optionally also be performed on subsequent update() / updateAad() /
+     *     finish() invocations.
      *
      *   If any of these conditions are not met, begin() must return
      *   ErrorCode::KEY_USER_NOT_AUTHENTICATED.
@@ -661,19 +678,19 @@
      *   structure, because it cannot add the DigestInfo structure.  Instead, the IKeyMintDevice
      *   must construct 0x00 || 0x01 || PS || 0x00 || M, where M is the provided message and PS is a
      *   random padding string at least eight bytes in length.  The size of the RSA key has to be at
-     *   least 11 bytes larger than the message, otherwise begin() must return
+     *   least 11 bytes larger than the message, otherwise finish() must return
      *   ErrorCode::INVALID_INPUT_LENGTH.
      *
      * o PaddingMode::RSA_PKCS1_1_1_5_ENCRYPT padding does not require a digest.
      *
-     * o PaddingMode::RSA_PSS padding requires a digest, which must match one of the padding values
+     * o PaddingMode::RSA_PSS padding requires a digest, which must match one of the digest values
      *   in the key authorizations, and which may not be Digest::NONE.  begin() must return
      *   ErrorCode::INCOMPATIBLE_DIGEST if this is not the case.  In addition, the size of the RSA
-     *   key must be at least 2 + D bytes larger than the output size of the digest, where D is the
-     *   size of the digest, in bytes.  Otherwise begin() must return
-     *   ErrorCode::INCOMPATIBLE_DIGEST.  The salt size must be D.
+     *   key must be at least (D + S + 9) bits, where D is the size of the digest (in bits) and
+     *   S is the size of the salt (in bits).  The salt size S must equal D, so the RSA key must
+     *   be at least (2*D + 9) bits. Otherwise begin() must return ErrorCode::INCOMPATIBLE_DIGEST.
      *
-     * o PaddingMode::RSA_OAEP padding requires a digest, which must match one of the padding values
+     * o PaddingMode::RSA_OAEP padding requires a digest, which must match one of the digest values
      *   in the key authorizations, and which may not be Digest::NONE.  begin() must return
      *   ErrorCode::INCOMPATIBLE_DIGEST if this is not the case.  RSA_OAEP padding also requires an
      *   MGF1 digest, specified with Tag::RSA_OAEP_MGF_DIGEST, which must match one of the MGF1
@@ -683,9 +700,9 @@
      *
      * -- EC Keys --
      *
-     * Private key operations (KeyPurpose::SIGN) need authorization of digest and padding, which
-     * means that the key authorizations must contain the specified values.  If not, begin() must
-     * return ErrorCode::INCOMPATIBLE_DIGEST.
+     * Private key operations (KeyPurpose::SIGN) need authorization of digest, which means that the
+     * key authorizations must contain the specified values.  If not, begin() must return
+     * ErrorCode::INCOMPATIBLE_DIGEST.
      *
      * -- AES Keys --
      *
@@ -804,7 +821,7 @@
     /**
      * Called by client to notify the IKeyMintDevice that the device has left the early boot
      * state, and that keys with the EARLY_BOOT_ONLY tag may no longer be used.  All attempts to use
-     * an EARLY_BOOT_ONLY key after this method is called must fail with Error::INVALID_KEY_BLOB.
+     * an EARLY_BOOT_ONLY key after this method is called must fail with Error::EARLY_BOOT_ENDED.
      */
     void earlyBootEnded();
 
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index c30c183..82c8a0d 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -40,31 +40,7 @@
      *
      * == Authorization Enforcement ==
      *
-     * Key authorization enforcement is performed primarily in begin().  The one exception is the
-     * case where the key has:
-     *
-     * o One or more Tag::USER_SECURE_IDs, and
-     *
-     * o Does not have a Tag::AUTH_TIMEOUT
-     *
-     * In this case, the key requires an authorization per operation, and the update method must
-     * receive a non-null and valid HardwareAuthToken.  For the auth token to be valid, all of the
-     * following has to be true:
-     *
-     *   o The HMAC field must validate correctly.
-     *
-     *   o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
-     *     the secure ID values in the token.
-     *
-     *   o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
-     *
-     *   o The challenge field in the auth token must contain the value returned from
-     *     IKeyMintDevice::begin(), given by the challenge field of the BeginResult structure.
-     *
-     *   If any of these conditions are not met, updateAad() must return
-     *   ErrorCode::KEY_USER_NOT_AUTHENTICATED.
-     *
-     * The caller must provide the auth token on every call to updateAad(), update() and finish().
+     * See the Authorization Enforcement section for the update() method.
      *
      *
      * For GCM encryption, the AEAD tag must be appended to the ciphertext by finish().  During
@@ -104,16 +80,22 @@
      *
      * == Authorization Enforcement ==
      *
-     * Key authorization enforcement is performed primarily in IKeyMintDevice::begin().  The one
-     * exception is the case where the key has:
+     * Key authorization enforcement is performed primarily in IKeyMintDevice::begin().  There are
+     * two exceptions to this:
      *
-     * o One or more Tag::USER_SECURE_IDs, and
+     *  1) Key with USER_SECURE_IDs but no AUTH_TIMEOUT
      *
-     * o Does not have a Tag::AUTH_TIMEOUT
+     *  2) Key with USER_SECURE_IDs and AUTH_TIMEOUT, but the device does not support secure time.
      *
-     * In this case, the key requires an authorization per operation, and the update method must
-     * receive a non-empty and valid HardwareAuthToken.  For the auth token to be valid, all of the
-     * following has to be true:
+     * The first exception is the case where the key:
+     *
+     *   o Has one or more Tag::USER_SECURE_IDs, and
+     *
+     *   o Does not have a Tag::AUTH_TIMEOUT
+     *
+     * In this case, the key requires an authorization per operation, and update() / updateAad() /
+     * finish() methods must receive a non-null and valid HardwareAuthToken.  For the auth token to
+     * be valid, all of the following has to be true:
      *
      *   o The HMAC field must validate correctly.
      *
@@ -125,10 +107,47 @@
      *   o The challenge field in the auth token must contain the challenge value contained in the
      *     BeginResult returned from IKeyMintDevice::begin().
      *
-     *   If any of these conditions are not met, update() must return
+     *   If any of these conditions are not met, the method must return
      *   ErrorCode::KEY_USER_NOT_AUTHENTICATED.
      *
-     * The caller must provide the auth token on every call to update() and finish().
+     * The caller must provide the auth token on every call to update(), updateAad() and finish().
+     *
+     *
+     * The second exception is the case where the key:
+     *
+     *   o Has one or more Tag::USER_SECURE_IDs, and
+     *
+     *   o Has a Tag::AUTH_TIMEOUT value, but the device does not have a source of secure time (as
+     *     indicated by the KeyMintHardwareInfo.timestampTokenRequired field).
+     *
+     * In this case, the key requires an per-operation authorization on the first call to update(),
+     * updateAad() or finish() for the operation, using the provided timeStampToken as a source of
+     * secure time.  For this timeStampToken to be valid, all of the following has to be true:
+     *
+     *   o The HMAC field must validate correctly.
+     *
+     *   o The challenge field in the auth token must contain the challenge value contained in the
+     *     BeginResult returned from IKeyMintDevice::begin().
+     *
+     * The resulting secure time value is then used to authenticate the HardwareAuthToken. For the
+     * auth token to be valid, all of the following has to be true:
+     *
+     *   o The HMAC field must validate correctly.
+     *
+     *   o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
+     *     the secure ID values in the token.
+     *
+     *   o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
+     *
+     *   o The challenge field in the auth token must contain the challenge value contained in the
+     *     BeginResult returned from IKeyMintDevice::begin().
+     *
+     *   o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be greater
+     *     than the provided secure timestamp.
+
+     *   If any of these conditions are not met, the method must return
+     *   ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+     *
      *
      * -- RSA keys --
      *
@@ -187,24 +206,7 @@
      * Key authorization enforcement is performed primarily in begin().  The exceptions are
      * authorization per operation keys and confirmation-required keys.
      *
-     * Authorization per operation keys are the case where the key has one or more
-     * Tag::USER_SECURE_IDs, and does not have a Tag::AUTH_TIMEOUT.  In this case, the key requires
-     * an authorization per operation, and the finish method must receive a non-empty and valid
-     * authToken.  For the auth token to be valid, all of the following has to be true:
-     *
-     *   o The HMAC field must validate correctly.
-     *
-     *   o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
-     *     the secure ID values in the token.
-     *
-     *   o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
-     *
-     *   o The challenge field in the auth token must contain the operation challenge.
-     *
-     *   If any of these conditions are not met, update() must return
-     *   ErrorCode::KEY_USER_NOT_AUTHENTICATED.
-     *
-     * The caller must provide the auth token on every call to update() and finish().
+     * Authorization per operation keys must be authorized as described for the update() method.
      *
      * Confirmation-required keys are keys that were generated with
      * Tag::TRUSTED_CONFIRMATION_REQUIRED.  For these keys, when doing a signing operation the
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index a29fb08..86c1717 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -29,28 +29,33 @@
  * validate the request and create certificates.
  *
  * This interface does not provide any way to use the generated and certified key pairs. It's
- * intended to be implemented by a HAL service that does other things with keys (e.g. Keymint).
+ * intended to be implemented by a HAL service that does other things with keys (e.g. KeyMint).
  *
- * The root of trust for secure provisioning is something called the "Boot Certificate Chain", or
- * BCC. The BCC is a chain of public key certificates, represented as COSE_Sign1 objects containing
- * COSE_Key representations of the public keys. The "root" of the BCC is
- * a device-unique public key, denoted DK_pub. All public keys in the BCC are device-unique. The
- * public key from each certificate in the chain is used to sign the next certificate in the
- * chain. The final, "leaf" certificate contains a public key, denoted KM_pub, whose corresponding
- * private key, denoted KM_priv, is available for use by the IRemotelyProvisionedComponent.
+ * The root of trust for secure provisioning is something called the Device Identifier Composition
+ * Engine (DICE) Chain. The DICE Chain is a chain of certificates, represented as COSE_Sign1 objects
+ * containing CBOR Web Tokens (CWT) which have descriptions about the stage of firmware being
+ * signed, including a COSE_Key representation of that stage's public key.
  *
- * BCC Design
- * ==========
+ * DICE Chain Design
+ * =================
  *
- * The BCC is designed to mirror the boot stages of a device, and to prove the content and integrity
- * of each firmware image. In a proper BCC, each boot stage hashes its own private key with the code
- * and any relevant configuration parameters of the next stage to produce a key pair for the next
- * stage. Each stage also uses its own private key to sign the public key of the next stage,
- * including in the certificate the hash of the next firmware stage, then loads the next stage,
- * passing the private key and certificate to it in a manner that does not leak the private key to
- * later boot stages. The BCC root key pair is generated by immutable code (e.g. ROM), from a
- * device-unique secret. After the device-unique secret is used, it must be made unavailable to any
- * later boot stage.
+ * For a more exhaustive and thorough look at DICE and the implementation used within this protocol,
+ * please see: https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md
+ *
+ * The DICE Chain is designed to mirror the boot stages of a device, and to prove the content and
+ * integrity of each firmware image. In a proper DICE Chain, each boot stage hashes its own private
+ * key material with the code and any relevant configuration parameters of the next stage to produce
+ * a Compound Device Identifier, or CDI, which is used as the secret key material for the next
+ * stage. From the CDI, a key pair - CDI_*_Pub and CDI_*_Priv - is derived and certified for the
+ * next stage by the current stages CDI_*_Priv. The next stage is then loaded and given its CDI and
+ * the DICE certificate chain generated so far in a manner that does not leak the previous stage's
+ * CDI_*_Priv or CDI to later boot stages. The final, "leaf" CDI certificate contains a public key,
+ * denoted CDI_Leaf_Pub, whose corresponding private key, denoted CDI_Leaf_Priv, is available for
+ * use by the IRemotelyProvisionedComponent.
+ *
+ * The root keypair is generated by immutable code (e.g. ROM), from a Unique Device Secret (UDS).
+ * The keypair that is generated from it can be referred to as the UDS_Pub/UDS_Priv keys. After the
+ * device-unique secret is used, it must be made unavailable to any later boot stage.
  *
  * In this way, booting the device incrementally builds a certificate chain that (a) identifies and
  * validates the integrity of every stage and (b) contains a set of public keys that correspond to
@@ -58,64 +63,64 @@
  * (given the necessary input), but no stage can compute the secret of any preceding stage. Updating
  * the firmware or configuration of any stage changes the key pair of that stage, and of all
  * subsequent stages, and no attacker who compromised the previous version of the updated firmware
- * can know or predict the post-update key pairs. It is recommended and expected that the BCC is
- * constructed using the Open Profile for DICE.
+ * can know or predict the post-update key pairs. It is recommended and expected that the DICE Chain
+ * is constructed using the Open Profile for DICE.
  *
- * When the provisioning server receives a message signed by KM_priv and containing a BCC that
- * chains from DK_pub to KM_pub, it can be certain that (barring vulnerabilities in some boot
- * stage), the CertificateRequest came from the device associated with DK_pub, running the specific
- * software identified by the certificates in the BCC. If the server has some mechanism for knowing
- * which the DK_pub values of "valid" devices, it can determine whether signing certificates is
- * appropriate.
+ * When the provisioning server receives a message signed by CDI_Leaf_Priv and containing a DICE
+ * chain that chains from UDS_Pub to CDI_Leaf_Pub, it can be certain that (barring vulnerabilities
+ * in some boot stage), the CertificateRequest came from the device associated with UDS_Pub, running
+ * the specific software identified by the certificates in the chain. If the server has some
+ * mechanism for knowing the hash values of compromised stages, it can determine whether signing
+ * certificates is appropriate.
  *
- * Degenerate BCCs
- * ===============
+ * Degenerate DICE Chains
+ * ======================
  *
- * While a proper BCC, as described above, reflects the complete boot sequence from boot ROM to the
- * secure area image of the IRemotelyProvisionedComponent, it's also possible to use a "degenerate"
- * BCC which consists only of a single, self-signed certificate containing the public key of a
- * hardware-bound key pair. This is an appopriate solution for devices which haven't implemented
- * everything necessary to produce a proper BCC, but can derive a unique key pair in the secure
- * area.  In this degenerate case, DK_pub is the same as KM_pub.
+ * While a proper DICE Chain, as described above, reflects the complete boot sequence from boot ROM
+ * to the secure area image of the IRemotelyProvisionedComponent, it's also possible to use a
+ * "degenerate" DICE Chain which consists only of a single, self-signed certificate containing the
+ * public key of a hardware-bound key pair. This is an appropriate solution for devices which
+ * haven't implemented everything necessary to produce a proper DICE Chain, but can derive a unique
+ * key pair in the secure area. In this degenerate case, UDS_Pub is the same as CDI_Leaf_Pub.
  *
- * BCC Privacy
- * ===========
+ * DICE Chain Privacy
+ * ==================
  *
- * Because the BCC constitutes an unspoofable, device-unique identifier, special care is taken to
- * prevent its availability to entities who may wish to track devices. Two precautions are taken:
+ * Because the DICE Chain constitutes an unspoofable, device-unique identifier, special care is
+ * taken to prevent its availability to entities who may wish to track devices. Three precautions
+ * are taken:
  *
- * 1.  The BCC is never exported from the IRemotelyProvisionedComponent except in encrypted
- *     form. The portion of the CertificateRequest that contains the BCC is encrypted using an
- *     Endpoint Encryption Key (EEK).  The EEK is provided in the form of a certificate chain whose
- *     root must be pre-provisioned into the secure area (hardcoding the roots into the secure area
- *     firmware image is a recommended approach). Multiple roots may be provisioned. If the provided
- *     EEK does not chain back to this already-known root, the IRemotelyProvisionedComponent must
- *     reject it.
+ * 1) The DICE chain is only handled by the native Remote Key Provisioning Daemon (RKPD) service on
+ *    the HLOS and is not exposed to apps running on device.
  *
- * 2.  Precaution 1 above ensures that only an entity with a valid EEK private key can decrypt the
- *     BCC. To make it feasible to build a provisioning server which cannot use the BCC to track
- *     devices, the CertificateRequest is structured so that the server can be partitioned into two
- *     components.  The "decrypter" decrypts the BCC, verifies DK_pub and the device's right to
- *     receive provisioned certificates, but does not see the public keys to be signed or the
- *     resulting certificates.  The "certifier" gets informed of the results of the decrypter's
- *     validation and sees the public keys to be signed and resulting certificates, but does not see
- *     the BCC.
+ * 2) The CDI_Leaf_Priv key cannot be used to sign arbitrary data.
  *
- * Test Mode
- * =========
+ * 3) Backend infrastructure does not correlate UDS_Pub with the certificates signed and sent back
+ *    to the device.
  *
- * The IRemotelyProvisionedComponent supports a test mode, allowing the generation of test key pairs
- * and test CertificateRequests. Test keys/requests are annotated as such, and the BCC used for test
- * CertificateRequests must contain freshly-generated keys, not the real BCC key pairs.
+ * Versioning
+ * ==========
+ * Versions 1 and 2 of the schema, as previously defined in DeviceInfo.aidl, diverge in
+ * functionality from Version 3. Version 3 removes the need to have testMode in function calls and
+ * deprecates the Endpoint Encryption Key (EEK) as well. Vendors implementing Version 1
+ * (Android S/12) or Version 2 (Android T/13) do not need to implement generateCertificateRequestV2.
+ * Vendors implementing Version 3 (Android U/14) need to implement generateCertificateRequestV2.
+ *
+ * For better coverage of changes from version to version, please see RKP_CHANGELOG.md in the root
+ * of the keymint interface directory.
+ *
  * @hide
  */
 @VintfStability
 interface IRemotelyProvisionedComponent {
     const int STATUS_FAILED = 1;
     const int STATUS_INVALID_MAC = 2;
+    // --------- START: Versions 1 and 2 Only ----------
     const int STATUS_PRODUCTION_KEY_IN_TEST_REQUEST = 3;
     const int STATUS_TEST_KEY_IN_PRODUCTION_REQUEST = 4;
     const int STATUS_INVALID_EEK = 5;
+    // --------- END: Versions 1 and 2 Only ------------
+    const int STATUS_REMOVED = 6;
 
     /**
      * @return info which contains information about the underlying IRemotelyProvisionedComponent
@@ -124,11 +129,14 @@
     RpcHardwareInfo getHardwareInfo();
 
     /**
-     * generateKeyPair generates a new ECDSA P-256 key pair that can be certified.  Note that this
-     * method only generates ECDSA P-256 key pairs, but the interface can be extended to add methods
-     * for generating keys for other algorithms, if necessary.
+     * generateKeyPair generates a new ECDSA P-256 key pair that can be attested by the remote
+     * server.
      *
-     * @param in boolean testMode indicates whether the generated key is for testing only. Test keys
+     * @param in boolean testMode this field is now deprecated. It is ignored by the implementation
+     *        in v3, but retained to simplify backwards compatibility support. V1 and V2
+     *        implementations must still respect the testMode flag.
+     *
+     *        testMode indicates whether the generated key is for testing only. Test keys
      *        are marked (see the definition of PublicKey in the MacedPublicKey structure) to
      *        prevent them from being confused with production keys.
      *
@@ -142,6 +150,11 @@
     byte[] generateEcdsaP256KeyPair(in boolean testMode, out MacedPublicKey macedPublicKey);
 
     /**
+     * This method has been removed in version 3 of the HAL. The header is kept around for
+     * backwards compatibility purposes. From v3, this method should raise a
+     * ServiceSpecificException with an error code of STATUS_REMOVED.
+     *
+     * For v1 and v2 implementations:
      * generateCertificateRequest creates a certificate request to be sent to the provisioning
      * server.
      *
@@ -158,7 +171,7 @@
      *        If testMode is false, the keysToCertify array must not contain any keys flagged as
      *        test keys. Otherwise, the method must return STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
      *
-     * @param in endpointEncryptionKey contains an X22519 public key which will be used to encrypt
+     * @param in endpointEncryptionKey contains an X25519 public key which will be used to encrypt
      *        the BCC. For flexibility, this is represented as a certificate chain, represented as a
      *        CBOR array of COSE_Sign1 objects, ordered from root to leaf. The leaf contains the
      *        X25519 encryption key, each other element is an Ed25519 key signing the next in the
@@ -167,9 +180,9 @@
      *
      *            EekChain = [ + SignedSignatureKey, SignedEek ]
      *
-     *            SignedSignatureKey = [              // COSE_Sign1
+     *            SignedSignatureKey = [              ; COSE_Sign1
      *                protected: bstr .cbor {
-     *                    1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
+     *                    1 : AlgorithmEdDSA / AlgorithmES256,  ; Algorithm
      *                },
      *                unprotected: {},
      *                payload: bstr .cbor SignatureKeyEd25519 /
@@ -178,69 +191,64 @@
      *                           bstr ECDSA(.cbor SignatureKeySignatureInput)
      *            ]
      *
-     *            SignatureKeyEd25519 = {                    // COSE_Key
-     *                 1 : 1,                         // Key type : Octet Key Pair
-     *                 3 : AlgorithmEdDSA,            // Algorithm
-     *                 -1 : 6,                        // Curve : Ed25519
-     *                 -2 : bstr                      // Ed25519 public key
+     *            SignatureKeyEd25519 = {             ; COSE_Key
+     *                 1 : 1,                         ; Key type : Octet Key Pair
+     *                 3 : AlgorithmEdDSA,            ; Algorithm
+     *                 -1 : 6,                        ; Curve : Ed25519
+     *                 -2 : bstr                      ; Ed25519 public key
      *            }
      *
-     *            SignatureKeyP256 = {
-     *                 1 : 2,                         // Key type : EC2
-     *                 3 : AlgorithmES256,            // Algorithm
-     *                 -1 : 1,                        // Curve: P256
-     *                 -2 : bstr,                     // X coordinate
-     *                 -3 : bstr                      // Y coordinate
+     *            SignatureKeyP256 = {                ; COSE_Key
+     *                 1 : 2,                         ; Key type : EC2
+     *                 3 : AlgorithmES256,            ; Algorithm
+     *                 -1 : 1,                        ; Curve: P256
+     *                 -2 : bstr,                     ; X coordinate
+     *                 -3 : bstr                      ; Y coordinate
      *            }
      *
      *            SignatureKeySignatureInput = [
      *                context: "Signature1",
-     *                body_protected: bstr .cbor {
-     *                    1 : AlgorithmEdDSA / AlgorithmES256,     // Algorithm
-     *                },
+     *                body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
      *                external_aad: bstr .size 0,
      *                payload: bstr .cbor SignatureKeyEd25519 /
      *                         bstr .cbor SignatureKeyP256
      *            ]
      *
-     *            SignedEek = [                       // COSE_Sign1
-     *                protected: bstr .cbor {
-     *                    1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
-     *                },
+     *            ; COSE_Sign1
+     *            SignedEek = [
+     *                protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
      *                unprotected: {},
      *                payload: bstr .cbor EekX25519 / .cbor EekP256,
      *                signature: bstr PureEd25519(.cbor EekSignatureInput) /
      *                           bstr ECDSA(.cbor EekSignatureInput)
      *            ]
      *
-     *            EekX25519 = {            // COSE_Key
-     *                1 : 1,               // Key type : Octet Key Pair
-     *                2 : bstr             // KID : EEK ID
-     *                3 : -25,             // Algorithm : ECDH-ES + HKDF-256
-     *                -1 : 4,              // Curve : X25519
-     *                -2 : bstr            // Ed25519 public key
+     *            EekX25519 = {            ; COSE_Key
+     *                1 : 1,               ; Key type : Octet Key Pair
+     *                2 : bstr             ; KID : EEK ID
+     *                3 : -25,             ; Algorithm : ECDH-ES + HKDF-256
+     *                -1 : 4,              ; Curve : X25519
+     *                -2 : bstr            ; X25519 public key
      *            }
      *
-     *            EekP256 = {              // COSE_Key
-     *                1 : 2,               // Key type : EC2
-     *                2 : bstr             // KID : EEK ID
-     *                3 : -25,             // Algorithm : ECDH-ES + HKDF-256
-     *                -1 : 1,              // Curve : P256
-     *                -2 : bstr            // Sender X coordinate
-     *                -3 : bstr            // Sender Y coordinate
+     *            EekP256 = {              ; COSE_Key
+     *                1 : 2,               ; Key type : EC2
+     *                2 : bstr             ; KID : EEK ID
+     *                3 : -25,             ; Algorithm : ECDH-ES + HKDF-256
+     *                -1 : 1,              ; Curve : P256
+     *                -2 : bstr            ; Sender X coordinate
+     *                -3 : bstr            ; Sender Y coordinate
      *            }
      *
      *            EekSignatureInput = [
      *                context: "Signature1",
-     *                body_protected: bstr .cbor {
-     *                    1 : AlgorithmEdDSA / AlgorithmES256,     // Algorithm
-     *                },
+     *                body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
      *                external_aad: bstr .size 0,
      *                payload: bstr .cbor EekX25519 / .cbor EekP256
      *            ]
      *
-     *            AlgorithmES256 = -7
-     *            AlgorithmEdDSA = -8
+     *            AlgorithmES256 = -7      ; RFC 8152 section 8.1
+     *            AlgorithmEdDSA = -8      ; RFC 8152 section 8.2
      *
      *        If the contents of endpointEncryptionKey do not match the SignedEek structure above,
      *        the method must return STATUS_INVALID_EEK.
@@ -249,7 +257,7 @@
      *        in the chain, which implies that it must not attempt to validate the signature.
      *
      *        If testMode is false, the method must validate the chain signatures, and must verify
-     *        that the public key in the root certifictate is in its pre-configured set of
+     *        that the public key in the root certificate is in its pre-configured set of
      *        authorized EEK root keys. If the public key is not in the database, or if signature
      *        verification fails, the method must return STATUS_INVALID_EEK.
      *
@@ -263,32 +271,207 @@
      * @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
      *        authenticate the keysToSign (see keysToSignMac output argument).
      *
-     * @return The of KeysToSign in the CertificateRequest structure. Specifically, it contains:
+     * @return The MAC of KeysToSign in the CertificateRequest structure. Specifically, it contains:
      *
      *            HMAC-256(EK_mac, .cbor KeysToMacStructure)
      *
      *        Where EK_mac is an ephemeral MAC key, found in ProtectedData (see below).  The MACed
      *        data is the "tag" field of a COSE_Mac0 structure like:
      *
-     *            MacedKeys = [                            // COSE_Mac0
+     *            MacedKeys = [                            ; COSE_Mac0
      *                protected : bstr .cbor {
-     *                    1 : 5,                           // Algorithm : HMAC-256
+     *                    1 : 5,                           ; Algorithm : HMAC-256
      *                },
      *                unprotected : {},
-     *                // Payload is PublicKeys from keysToSign argument, in provided order.
+     *                ; Payload is PublicKeys from keysToSign argument, in provided order.
      *                payload: bstr .cbor [ * PublicKey ],
      *                tag: bstr
      *            ]
      *
      *            KeysToMacStructure = [
      *                context : "MAC0",
-     *                protected : bstr .cbor { 1 : 5 },    // Algorithm : HMAC-256
+     *                protected : bstr .cbor { 1 : 5 },    ; Algorithm : HMAC-256
      *                external_aad : bstr .size 0,
-     *                // Payload is PublicKeys from keysToSign argument, in provided order.
+     *                ; Payload is PublicKeys from keysToSign argument, in provided order.
      *                payload : bstr .cbor [ * PublicKey ]
      *            ]
      */
     byte[] generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
             in byte[] endpointEncryptionCertChain, in byte[] challenge, out DeviceInfo deviceInfo,
             out ProtectedData protectedData);
+
+    /**
+     * generateCertificateRequestV2 creates a certificate signing request to be sent to the
+     * provisioning server.
+     *
+     * @param in MacedPublicKey[] keysToSign contains the set of keys to certify. The
+     *        IRemotelyProvisionedComponent must validate the MACs on each key.  If any entry in the
+     *        array lacks a valid MAC, the method must return STATUS_INVALID_MAC.
+     *
+     * @param in challenge contains a byte string from the provisioning server which will be
+     *        included in the signed data of the CSR structure. Different provisioned backends may
+     *        use different semantic data for this field, but the supported sizes must be between 32
+     *        and 64 bytes, inclusive.
+     *
+     * @return the following CBOR Certificate Signing Request (Csr) serialized into a byte array:
+     *
+     * Csr = AuthenticatedMessage<CsrPayload>
+     *
+     * CsrPayload = [                      ; CBOR Array defining the payload for Csr
+     *     version: 1,                     ; The CsrPayload CDDL Schema version.
+     *     CertificateType,                ; The type of certificate being requested.
+     *     DeviceInfo,                     ; Defined in DeviceInfo.aidl
+     *     challenge: bstr .size (32..64), ; Provided by the method parameters
+     *     KeysToSign,                     ; Provided by the method parameters
+     * ]
+     *
+     *  ; A tstr identifying the type of certificate. The set of supported certificate types may
+     *  ; be extended without requiring a version bump of the HAL. Custom certificate types may
+     *  ; be used, but the provisioning server may reject the request for an unknown certificate
+     *  ; type. The currently defined certificate types are:
+     *  ;  - "widevine"
+     *  ;  - "keymint"
+     *  CertificateType = tstr
+     *
+     * KeysToSign = [ * PublicKey ]   ; Please see MacedPublicKey.aidl for the PublicKey definition.
+     *
+     * AuthenticatedMessage<T> = [
+     *    version: 3,              ; The AuthenticatedMessage CDDL Schema version.
+     *    UdsCerts,
+     *    DiceCertChain,
+     *    SignedData<T>,
+     * ]
+     *
+     * ; COSE_Sign1 (untagged)
+     * SignedData<T> = [
+     *     protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+     *     unprotected: {},
+     *     payload: bstr .cbor T / nil,
+     *     signature: bstr         ; PureEd25519(CDI_Leaf_Priv, bstr .cbor SignedDataSigStruct<T>) /
+     *                             ; ECDSA(CDI_Leaf_Priv, bstr .cbor SignedDataSigStruct<T>)
+     * ]
+     *
+     * ; Sig_structure for SignedData
+     * SignedDataSigStruct<T> = [
+     *     context: "Signature1",
+     *     protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+     *     external_aad: bstr .size 0,
+     *     payload: bstr .cbor T
+     * ]
+     *
+     * ; UdsCerts allows the platform to provide additional certifications for the UDS_Pub. For
+     * ; example, this could be provided by the hardware vendor, who certifies all of their chips.
+     * ; The SignerName is a free-form string describing who generated the signature. The root
+     * ; certificate will need to be communicated to the verifier out of band, along with the
+     * ; SignerName that is expected for the given root certificate.
+     * UdsCerts = {
+     *     * SignerName => UdsCertChain
+     * }
+     *
+     * ; SignerName is a string identifier that indicates both the signing authority as
+     * ; well as the format of the UdsCertChain
+     * SignerName = tstr
+     *
+     * UdsCertChain = [
+     *     2* X509Certificate       ; Root -> ... -> Leaf. "Root" is the vendor self-signed
+     *                              ; cert, "Leaf" contains UDS_Public. There may also be
+     *                              ; intermediate certificates between Root and Leaf.
+     * ]
+     *
+     * ; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or EdDSA)
+     * X509Certificate = bstr
+     *
+     * ; The DICE Chain contains measurements about the device firmware.
+     * ; The first entry in the DICE Chain is the UDS_Pub, encoded as a COSE_key. All entries
+     * ; after the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN)
+     * ; Note that there is no DiceChainEntry for UDS_pub, only a "bare" COSE_key.
+     * DiceCertChain = [
+     *     PubKeyEd25519 / PubKeyECDSA256,  ; UDS_Pub
+     *     + DiceChainEntry,                ; First CDI_Certificate -> Last CDI_Certificate
+     *                                      ; Last certificate corresponds to KeyMint's DICE key.
+     * ]
+     *
+     * ; This is the signed payload for each entry in the DICE chain. Note that the "Configuration
+     * ; Input Values" described by the Open Profile are not used here. Instead, the DICE chain
+     * ; defines its own configuration values for the Configuration Descriptor field. See
+     * ; the Open Profile for DICE for more details on the fields. SHA256 and SHA512 are acceptable
+     * ; hash algorithms. The digest bstr values in the payload are the digest values without any
+     * ; padding. Note that for SHA256, this implies the digest bstr is 32 bytes. This is an
+     * ; intentional, minor deviation from Open Profile for DICE, which specifies all digests are
+     * ; 64 bytes.
+     * DiceChainEntryPayload = {                    ; CWT [RFC8392]
+     *     1 : tstr,                                ; Issuer
+     *     2 : tstr,                                ; Subject
+     *     -4670552 : bstr .cbor PubKeyEd25519 /
+     *                bstr .cbor PubKeyECDSA256,    ; Subject Public Key
+     *     -4670553 : bstr                          ; Key Usage
+     *
+     *     ; NOTE: All of the following fields may be omitted for a "Degenerate DICE Chain", as
+     *     ;       described above.
+     *     -4670545 : bstr,                         ; Code Hash
+     *     ? -4670546 : bstr,                       ; Code Descriptor
+     *     ? -4670547 : bstr,                       ; Configuration Hash
+     *     -4670548 : bstr .cbor {                  ; Configuration Descriptor
+     *         ? -70002 : tstr,                         ; Component name
+     *         ? -70003 : int,                          ; Firmware version
+     *         ? -70004 : null,                         ; Resettable
+     *     },
+     *     -4670549 : bstr,                         ; Authority Hash
+     *     ? -4670550 : bstr,                       ; Authority Descriptor
+     *     -4670551 : bstr,                         ; Mode
+     * }
+     *
+     * ; Each entry in the DICE chain is a DiceChainEntryPayload signed by the key from the previous
+     * ; entry in the DICE chain array.
+     * DiceChainEntry = [                            ; COSE_Sign1 (untagged)
+     *     protected : bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+     *     unprotected: {},
+     *     payload: bstr .cbor DiceChainEntryPayload,
+     *     signature: bstr ; PureEd25519(SigningKey, bstr .cbor DiceChainEntryInput) /
+     *                     ; ECDSA(SigningKey, bstr .cbor DiceChainEntryInput)
+     *                     ; See RFC 8032 for details of how to encode the signature value
+     *                     ; for Ed25519.
+     * ]
+     *
+     * DiceChainEntryInput = [
+     *     context: "Signature1",
+     *     protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+     *     external_aad: bstr .size 0,
+     *     payload: bstr .cbor DiceChainEntryPayload
+     * ]
+     *
+     * ; The following section defines some types that are reused throughout the above
+     * ; data structures.
+     * PubKeyX25519 = {                 ; COSE_Key
+     *      1 : 1,                      ; Key type : Octet Key Pair
+     *     -1 : 4,                      ; Curve : X25519
+     *     -2 : bstr                    ; Sender X25519 public key
+     * }
+     *
+     * PubKeyEd25519 = {                ; COSE_Key
+     *     1 : 1,                       ; Key type : octet key pair
+     *     3 : AlgorithmEdDSA,          ; Algorithm : EdDSA
+     *     -1 : 6,                      ; Curve : Ed25519
+     *     -2 : bstr                    ; X coordinate, little-endian
+     * }
+     *
+     * PubKeyEcdhP256 = {               ; COSE_Key
+     *      1 : 2,                      ; Key type : EC2
+     *      -1 : 1,                     ; Curve : P256
+     *      -2 : bstr                   ; Sender X coordinate
+     *      -3 : bstr                   ; Sender Y coordinate
+     * }
+     *
+     * PubKeyECDSA256 = {               ; COSE_Key
+     *     1 : 2,                       ; Key type : EC2
+     *     3 : AlgorithmES256,          ; Algorithm : ECDSA w/ SHA-256
+     *     -1 : 1,                      ; Curve: P256
+     *     -2 : bstr,                   ; X coordinate
+     *     -3 : bstr                    ; Y coordinate
+     * }
+     *
+     * AlgorithmES256 = -7
+     * AlgorithmEdDSA = -8
+     */
+    byte[] generateCertificateRequestV2(in MacedPublicKey[] keysToSign, in byte[] challenge);
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index 57285a3..4c2be89 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -99,8 +99,7 @@
      * X.509 certificates ordered such that each certificate is signed by the subsequent one, up to
      * the root which must be self-signed (or contain a fake signature in the case of case 4 above).
      * The first certificate in the chain signs the public key info of the newly-generated or
-     * newly-imported key pair.  In the attestation cases (1 and 2 above), the first certificate
-     * must also satisfy some other requirements:
+     * newly-imported key pair.  The first certificate must also satisfy some other requirements:
      *
      * o It must have the serial number provided in Tag::CERTIFICATE_SERIAL, or default to 1 if the
      *   tag is not provided.
@@ -119,7 +118,8 @@
      *    - the keyAgreement bit set iff the attested key has KeyPurpose::AGREE_KEY, and
      *    - the keyCertSignBit set iff the attested key has KeyPurpose::ATTEST_KEY.
      *
-     * o it must contain a KeyDescription attestation extension with OID 1.3.6.1.4.1.11129.2.1.17.
+     * In the attestation cases (1 and 2 above), the first certificate must contain a
+     * KeyDescription attestation extension with OID 1.3.6.1.4.1.11129.2.1.17.
      *
      * The KeyDescription content is defined by the following ASN.1 schema, which is mostly a
      * straightforward translation of the KeyMint tag/value parameter lists to ASN.1.
@@ -158,12 +158,23 @@
      *     Failed                     (3),
      * }
      *
+     * -- Note that the AuthorizationList SEQUENCE is also used in IKeyMintDevice::importWrappedKey
+     * -- as a way of describing the authorizations associated with a key that is being securely
+     * -- imported.  As such, it includes the ability to describe tags that are only relevant for
+     * -- symmetric keys, and which will never appear in the attestation extension of an X.509
+     * -- certificate that holds the public key part of an asymmetric keypair. Importing a wrapped
+     * -- key also allows the use of Tag::USER_SECURE_ID, which is never included in an attestation
+     * -- extension because it has no meaning off-device.
+     *
      * AuthorizationList ::= SEQUENCE {
      *     purpose                    [1] EXPLICIT SET OF INTEGER OPTIONAL,
      *     algorithm                  [2] EXPLICIT INTEGER OPTIONAL,
      *     keySize                    [3] EXPLICIT INTEGER OPTIONAL,
+     *     blockMode                  [4] EXPLICIT SET OF INTEGER OPTIONAL, -- symmetric only
      *     digest                     [5] EXPLICIT SET OF INTEGER OPTIONAL,
      *     padding                    [6] EXPLICIT SET OF INTEGER OPTIONAL,
+     *     callerNonce                [7] EXPLICIT NULL OPTIONAL, -- symmetric only
+     *     minMacLength               [8] EXPLICIT INTEGER OPTIONAL, -- symmetric only
      *     ecCurve                    [10] EXPLICIT INTEGER OPTIONAL,
      *     rsaPublicExponent          [200] EXPLICIT INTEGER OPTIONAL,
      *     mgfDigest                  [203] EXPLICIT SET OF INTEGER OPTIONAL,
@@ -173,6 +184,7 @@
      *     originationExpireDateTime  [401] EXPLICIT INTEGER OPTIONAL,
      *     usageExpireDateTime        [402] EXPLICIT INTEGER OPTIONAL,
      *     usageCountLimit            [405] EXPLICIT INTEGER OPTIONAL,
+     *     userSecureId               [502] EXPLICIT INTEGER OPTIONAL, -- only used on import
      *     noAuthRequired             [503] EXPLICIT NULL OPTIONAL,
      *     userAuthType               [504] EXPLICIT INTEGER OPTIONAL,
      *     authTimeout                [505] EXPLICIT INTEGER OPTIONAL,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
index fd103ef..32e71a7 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
@@ -23,7 +23,7 @@
 @VintfStability
 @Backing(type="int")
 enum KeyPurpose {
-    /* Usable with RSA, 3DES and AES keys. */
+    /* Usable with 3DES and AES keys. */
     ENCRYPT = 0,
 
     /* Usable with RSA, 3DES and AES keys. */
@@ -32,7 +32,7 @@
     /* Usable with RSA, EC and HMAC keys. */
     SIGN = 2,
 
-    /* Usable with RSA, EC and HMAC keys. */
+    /* Usable with HMAC keys. */
     VERIFY = 3,
 
     /* 4 is reserved */
diff --git a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl b/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
index ad97443..275e322 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
@@ -28,21 +28,22 @@
      * only to the secure environment, as proof that the public key was generated by that
      * environment. In CDDL, assuming the contained key is a P-256 public key:
      *
-     *     MacedPublicKey = [                     // COSE_Mac0
-     *         protected: bstr .cbor { 1 : 5},    // Algorithm : HMAC-256
+     *     MacedPublicKey = [                     ; COSE_Mac0
+     *         protected: bstr .cbor { 1 : 5},    ; Algorithm : HMAC-256
      *         unprotected: { },
      *         payload : bstr .cbor PublicKey,
      *         tag : bstr HMAC-256(K_mac, MAC_structure)
      *     ]
      *
-     *     PublicKey = {               // COSE_Key
-     *         1 : 2,                  // Key type : EC2
-     *         3 : -7,                 // Algorithm : ES256
-     *         -1 : 1,                 // Curve : P256
-     *         -2 : bstr,              // X coordinate, little-endian
-     *         -3 : bstr,              // Y coordinate, little-endian
-     *         ? -70000 : nil          // Presence indicates this is a test key.  If set, K_mac is
-     *                                 // all zeros.
+     *     ; NOTE: -70000 is deprecated for v3 HAL implementations.
+     *     PublicKey = {               ; COSE_Key
+     *         1 : 2,                  ; Key type : EC2
+     *         3 : -7,                 ; Algorithm : ES256
+     *         -1 : 1,                 ; Curve : P256
+     *         -2 : bstr,              ; X coordinate, little-endian
+     *         -3 : bstr,              ; Y coordinate, little-endian
+     *         -70000 : nil            ; Presence indicates this is a test key. If set, K_mac is
+     *                                 ; all zeros.
      *     },
      *
      *     MAC_structure = [
@@ -51,9 +52,6 @@
      *         external_aad : bstr .size 0,
      *         payload : bstr .cbor PublicKey
      *     ]
-     *
-     * if a non-P256 public key were contained, the contents of the PublicKey map would change a
-     * little; see RFC 8152 for details.
      */
     byte[] macedKey;
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl b/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
index e71a9c9..6ff4b29 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
@@ -26,7 +26,7 @@
 @VintfStability
 @Backing(type="int")
 enum PaddingMode {
-    NONE = 1, /* deprecated */
+    NONE = 1,
     RSA_OAEP = 2,
     RSA_PSS = 3,
     RSA_PKCS1_1_5_ENCRYPT = 4,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
index 8b3875b..d59508b 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
@@ -17,9 +17,13 @@
 package android.hardware.security.keymint;
 
 /**
+ * NOTE: ProtectedData has been removed as of version 3, but is kept around for backwards
+ * compatibility reasons. For versions 1 and 2:
+ *
  * ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
  * authenticate the keysToSign (see keysToSignMac output argument of
  * IRemotelyProvisionedComponent.generateCertificateRequest).
+ *
  * @hide
  */
 @VintfStability
@@ -33,201 +37,201 @@
      *   - None of the CBOR in ProtectedData uses CBOR tags. If an implementation includes
      *     tags, parsers may reject the data.
      *
-     *     ProtectedData = [               // COSE_Encrypt
+     *     ProtectedData = [               ; COSE_Encrypt
      *         protected: bstr .cbor {
-     *             1 : 3                   // Algorithm : AES-GCM 256
+     *             1 : 3                   ; Algorithm : AES-GCM 256
      *         },
      *         unprotected: {
-     *             5 : bstr .size 12       // IV
+     *             5 : bstr .size 12       ; IV
      *         },
-     *         ciphertext: bstr,           // AES-GCM-256(K, .cbor ProtectedDataPayload)
-     *                                     // Where the encryption key 'K' is derived as follows:
-     *                                     // ikm = ECDH(EEK_pub, Ephemeral_priv)
-     *                                     // salt = null
-     *                                     // info = .cbor Context (see below)
-     *                                     // K = HKDF-SHA-256(ikm, salt, info)
+     *         ciphertext: bstr,           ; AES-GCM-256(K, .cbor ProtectedDataPayload)
+     *                                     ; Where the encryption key 'K' is derived as follows:
+     *                                     ; ikm = ECDH(EEK_pub, Ephemeral_priv)
+     *                                     ; salt = null
+     *                                     ; info = .cbor Context (see below)
+     *                                     ; K = HKDF-SHA-256(ikm, salt, info)
      *         recipients : [
-     *             [                       // COSE_Recipient
+     *             [                       ; COSE_Recipient
      *                 protected : bstr .cbor {
-     *                     1 : -25         // Algorithm : ECDH-ES + HKDF-256
+     *                     1 : -25         ; Algorithm : ECDH-ES + HKDF-256
      *                 },
      *                 unprotected : {
-     *                     -1 : PubKeyX25519 / PubKeyEcdhP256  // Ephemeral_pub
-     *                     4 : bstr,       // KID : EEK ID
+     *                     -1 : PubKeyX25519 / PubKeyEcdhP256  ; Ephemeral_pub
+     *                     4 : bstr,       ; KID : EEK ID
      *                 },
      *                 ciphertext : nil
      *             ]
      *         ]
      *     ]
      *
-     *     // The COSE_KDF_Context that is used to derive the ProtectedData encryption key with
-     *     // HKDF. See details on use in ProtectedData comments above.
+     *     ; The COSE_KDF_Context that is used to derive the ProtectedData encryption key with
+     *     ; HKDF. See details on use in ProtectedData comments above.
      *     Context = [
-     *         AlgorithmID : 3             // AES-GCM 256
+     *         AlgorithmID : 3             ; AES-GCM 256
      *         PartyUInfo : [
      *             identity : bstr "client"
      *             nonce : bstr .size 0,
-     *             other : bstr            // Ephemeral_pub
+     *             other : bstr            ; Ephemeral_pub
      *         ],
      *         PartyVInfo : [
      *             identity : bstr "server",
      *             nonce : bstr .size 0,
-     *             other : bstr            // EEK pubkey
+     *             other : bstr            ; EEK pubkey
      *         ],
      *         SuppPubInfo : [
-     *             256,                    // Output key length
+     *             256,                    ; Output key length
      *             protected : bstr .size 0
      *         ]
      *     ]
      *
-     *     // The data that is encrypted and included in ProtectedData ciphertext (see above).
+     *     ; The data that is encrypted and included in ProtectedData ciphertext (see above).
      *     ProtectedDataPayload [
      *         SignedMac,
      *         Bcc,
      *         ? AdditionalDKSignatures,
      *     ]
      *
-     *     // AdditionalDKSignatures allows the platform to provide additional certifications
-     *     // for the DK_pub. For example, this could be provided by the hardware vendor, who
-     *     // certifies all of their devices. The SignerName is a free-form string describing
-     *     // who generated the signature.
+     *     ; AdditionalDKSignatures allows the platform to provide additional certifications
+     *     ; for the DK_pub. For example, this could be provided by the hardware vendor, who
+     *     ; certifies all of their devices. The SignerName is a free-form string describing
+     *     ; who generated the signature.
      *     AdditionalDKSignatures = {
      *         + SignerName => DKCertChain
      *     }
      *
-     *     // SignerName is a string identifier that indicates both the signing authority as
-     *     // well as the format of the DKCertChain
+     *     ; SignerName is a string identifier that indicates both the signing authority as
+     *     ; well as the format of the DKCertChain
      *     SignerName = tstr
      *
      *     DKCertChain = [
-     *         2* X509Certificate       // Root -> ... -> Leaf. "Root" is the vendor self-signed
-     *                                  // cert, "Leaf" contains DK_pub. There may also be
-     *                                  // intermediate certificates between Root and Leaf.
+     *         2* X509Certificate       ; Root -> ... -> Leaf. "Root" is the vendor self-signed
+     *                                  ; cert, "Leaf" contains DK_pub. There may also be
+     *                                  ; intermediate certificates between Root and Leaf.
      *     ]
      *
-     *     // A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or edDSA)
+     *     ; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or edDSA)
      *     X509Certificate = bstr
      *
-     *     // The SignedMac, which authenticates the MAC key that is used to authenticate the
-     *     // keysToSign.
-     *     SignedMac = [                                // COSE_Sign1
-     *         bstr .cbor {                             // Protected params
-     *             1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
+     *     ; The SignedMac, which authenticates the MAC key that is used to authenticate the
+     *     ; keysToSign.
+     *     SignedMac = [                                ; COSE_Sign1
+     *         bstr .cbor {                             ; Protected params
+     *             1 : AlgorithmEdDSA / AlgorithmES256, ; Algorithm
      *         },
-     *         {},                                      // Unprotected params
-     *         bstr .size 32,                           // Payload: MAC key
-     *         bstr // PureEd25519(KM_priv, bstr .cbor SignedMac_structure) /
-     *              // ECDSA(KM_priv, bstr .cbor SignedMac_structure)
+     *         {},                                      ; Unprotected params
+     *         bstr .size 32,                           ; Payload: MAC key
+     *         bstr ; PureEd25519(KM_priv, bstr .cbor SignedMac_structure) /
+     *              ; ECDSA(KM_priv, bstr .cbor SignedMac_structure)
      *     ]
      *
-     *     SignedMac_structure = [                      //  COSE Sig_structure
+     *     SignedMac_structure = [                      ;  COSE Sig_structure
      *         "Signature1",
-     *         bstr .cbor {                             // Protected params
-     *             1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
+     *         bstr .cbor {                             ; Protected params
+     *             1 : AlgorithmEdDSA / AlgorithmES256, ; Algorithm
      *         },
      *         bstr .cbor SignedMacAad,
-     *         bstr .size 32                            // MAC key
+     *         bstr .size 32                            ; MAC key
      *     ]
      *
      *     SignedMacAad = [
-     *         challenge : bstr .size (32..64),   // Size between 32 - 64
-     *                                            // bytes inclusive
+     *         challenge : bstr .size (32..64),   ; Size between 32 - 64
+     *                                            ; bytes inclusive
      *         VerifiedDeviceInfo,
-     *         tag: bstr                 // This is the tag from COSE_Mac0 of
-     *                                   // KeysToCertify, to tie the key set to
-     *                                   // the signature.
+     *         tag: bstr                 ; This is the tag from COSE_Mac0 of
+     *                                   ; KeysToCertify, to tie the key set to
+     *                                   ; the signature.
      *     ]
      *
-     *     VerifiedDeviceInfo = DeviceInfo  // See DeviceInfo.aidl
+     *     VerifiedDeviceInfo = DeviceInfo  ; See DeviceInfo.aidl
      *
-     *     // The BCC is the boot certificate chain, containing measurements about the device
-     *     // boot chain. The BCC generally follows the Open Profile for DICE specification at
-     *     // https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md.
-     *     //
-     *     // The first entry in the Bcc is the DK_pub, encoded as a COSE_key. All entries after
-     *     // the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN).
-     *     // Note that there is no BccEntry for DK_pub, only a "bare" COSE_key.
+     *     ; The BCC is the boot certificate chain, containing measurements about the device
+     *     ; boot chain. The BCC generally follows the Open Profile for DICE specification at
+     *     ; https:;pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md.
+     *     ;
+     *     ; The first entry in the Bcc is the DK_pub, encoded as a COSE_key. All entries after
+     *     ; the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN).
+     *     ; Note that there is no BccEntry for DK_pub, only a "bare" COSE_key.
      *     Bcc = [
-     *         PubKeyEd25519 / PubKeyECDSA256, // DK_pub
-     *         + BccEntry,                     // Root -> leaf (KM_pub)
+     *         PubKeyEd25519 / PubKeyECDSA256, ; DK_pub
+     *         + BccEntry,                     ; Root -> leaf (KM_pub)
      *     ]
      *
-     *     // This is the signed payload for each entry in the Bcc. Note that the "Configuration
-     *     // Input Values" described by the Open Profile are not used here. Instead, the Bcc
-     *     // defines its own configuration values for the Configuration Descriptor field. See
-     *     // the Open Profile for DICE for more details on the fields. All hashes are SHA256.
-     *     BccPayload = {                               // CWT [RFC8392]
-     *         1 : tstr,                                // Issuer
-     *         2 : tstr,                                // Subject
+     *     ; This is the signed payload for each entry in the Bcc. Note that the "Configuration
+     *     ; Input Values" described by the Open Profile are not used here. Instead, the Bcc
+     *     ; defines its own configuration values for the Configuration Descriptor field. See
+     *     ; the Open Profile for DICE for more details on the fields. All hashes are SHA256.
+     *     BccPayload = {                               ; CWT [RFC8392]
+     *         1 : tstr,                                ; Issuer
+     *         2 : tstr,                                ; Subject
      *         -4670552 : bstr .cbor PubKeyEd25519 /
-     *                    bstr .cbor PubKeyECDSA256,    // Subject Public Key
-     *         -4670553 : bstr                          // Key Usage
+     *                    bstr .cbor PubKeyECDSA256,    ; Subject Public Key
+     *         -4670553 : bstr                          ; Key Usage
      *
-     *         // NOTE: All of the following fields may be omitted for a "Degenerate BCC", as
-     *         //       described by IRemotelyProvisionedComponent.aidl.
-     *         -4670545 : bstr,                         // Code Hash
-     *         ? -4670546 : bstr,                       // Code Descriptor
-     *         ? -4670547 : bstr,                       // Configuration Hash
-     *         -4670548 : bstr .cbor {                  // Configuration Descriptor
-     *             ? -70002 : tstr,                         // Component name
-     *             ? -70003 : int,                          // Firmware version
-     *             ? -70004 : null,                         // Resettable
+     *         ; NOTE: All of the following fields may be omitted for a "Degenerate BCC", as
+     *         ;       described by IRemotelyProvisionedComponent.aidl.
+     *         -4670545 : bstr,                         ; Code Hash
+     *         ? -4670546 : bstr,                       ; Code Descriptor
+     *         ? -4670547 : bstr,                       ; Configuration Hash
+     *         -4670548 : bstr .cbor {                  ; Configuration Descriptor
+     *             ? -70002 : tstr,                         ; Component name
+     *             ? -70003 : int,                          ; Firmware version
+     *             ? -70004 : null,                         ; Resettable
      *         },
-     *         -4670549 : bstr,                         // Authority Hash
-     *         ? -4670550 : bstr,                       // Authority Descriptor
-     *         -4670551 : bstr,                         // Mode
+     *         -4670549 : bstr,                         ; Authority Hash
+     *         ? -4670550 : bstr,                       ; Authority Descriptor
+     *         -4670551 : bstr,                         ; Mode
      *     }
      *
-     *     // Each entry in the Bcc is a BccPayload signed by the key from the previous entry
-     *     // in the Bcc array.
-     *     BccEntry = [                                  // COSE_Sign1 (untagged)
+     *     ; Each entry in the Bcc is a BccPayload signed by the key from the previous entry
+     *     ; in the Bcc array.
+     *     BccEntry = [                                  ; COSE_Sign1 (untagged)
      *         protected : bstr .cbor {
-     *             1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
+     *             1 : AlgorithmEdDSA / AlgorithmES256,  ; Algorithm
      *         },
      *         unprotected: {},
      *         payload: bstr .cbor BccPayload,
-     *         signature: bstr // PureEd25519(SigningKey, bstr .cbor BccEntryInput) /
-     *                         // ECDSA(SigningKey, bstr .cbor BccEntryInput)
-     *         // See RFC 8032 for details of how to encode the signature value for Ed25519.
+     *         signature: bstr ; PureEd25519(SigningKey, bstr .cbor BccEntryInput) /
+     *                         ; ECDSA(SigningKey, bstr .cbor BccEntryInput)
+     *         ; See RFC 8032 for details of how to encode the signature value for Ed25519.
      *     ]
      *
      *     BccEntryInput = [
      *         context: "Signature1",
      *         protected: bstr .cbor {
-     *             1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
+     *             1 : AlgorithmEdDSA / AlgorithmES256,  ; Algorithm
      *         },
      *         external_aad: bstr .size 0,
      *         payload: bstr .cbor BccPayload
      *     ]
      *
-     *     // The following section defines some types that are reused throughout the above
-     *     // data structures.
-     *     PubKeyX25519 = {                 // COSE_Key
-     *          1 : 1,                      // Key type : Octet Key Pair
-     *         -1 : 4,                      // Curve : X25519
-     *         -2 : bstr                    // Sender X25519 public key
+     *     ; The following section defines some types that are reused throughout the above
+     *     ; data structures.
+     *     PubKeyX25519 = {                 ; COSE_Key
+     *          1 : 1,                      ; Key type : Octet Key Pair
+     *         -1 : 4,                      ; Curve : X25519
+     *         -2 : bstr                    ; Sender X25519 public key
      *     }
      *
-     *     PubKeyEd25519 = {                // COSE_Key
-     *         1 : 1,                       // Key type : octet key pair
-     *         3 : AlgorithmEdDSA,          // Algorithm : EdDSA
-     *         -1 : 6,                      // Curve : Ed25519
-     *         -2 : bstr                    // X coordinate, little-endian
+     *     PubKeyEd25519 = {                ; COSE_Key
+     *         1 : 1,                       ; Key type : octet key pair
+     *         3 : AlgorithmEdDSA,          ; Algorithm : EdDSA
+     *         -1 : 6,                      ; Curve : Ed25519
+     *         -2 : bstr                    ; X coordinate, little-endian
      *     }
      *
-     *     PubKeyEcdhP256 = {               // COSE_Key
-     *          1 : 2,                      // Key type : EC2
-     *          -1 : 1,                     // Curve : P256
-     *          -2 : bstr                   // Sender X coordinate
-     *          -3 : bstr                   // Sender Y coordinate
+     *     PubKeyEcdhP256 = {               ; COSE_Key
+     *          1 : 2,                      ; Key type : EC2
+     *          -1 : 1,                     ; Curve : P256
+     *          -2 : bstr                   ; Sender X coordinate
+     *          -3 : bstr                   ; Sender Y coordinate
      *     }
      *
-     *     PubKeyECDSA256 = {               // COSE_Key
-     *         1 : 2,                       // Key type : EC2
-     *         3 : AlgorithmES256,          // Algorithm : ECDSA w/ SHA-256
-     *         -1 : 1,                      // Curve: P256
-     *         -2 : bstr,                   // X coordinate
-     *         -3 : bstr                    // Y coordinate
+     *     PubKeyECDSA256 = {               ; COSE_Key
+     *         1 : 2,                       ; Key type : EC2
+     *         3 : AlgorithmES256,          ; Algorithm : ECDSA w/ SHA-256
+     *         -1 : 1,                      ; Curve: P256
+     *         -2 : bstr,                   ; X coordinate
+     *         -3 : bstr                    ; Y coordinate
      *     }
      *
      *     AlgorithmES256 = -7
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index b28ebcb..47361d5 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -186,10 +186,16 @@
      * Tag::RSA_OAEP_MGF_DIGEST specifies the MGF1 digest algorithms that may be used with RSA
      * encryption/decryption with OAEP padding.  Possible values are defined by the Digest enum.
      *
-     * This tag is repeatable for key generation/import.  RSA cipher operations with OAEP padding
-     * must specify an MGF1 digest in the params argument of begin(). If this tag is missing or the
-     * specified digest is not in the MGF1 digests associated with the key then begin operation must
-     * fail with ErrorCode::INCOMPATIBLE_MGF_DIGEST.
+     * This tag is repeatable for key generation/import.
+     *
+     * If the caller specifies an MGF1 digest in the params argument of begin(), that digest must be
+     * present as an RSA_OAEP_MGF_DIGEST value in the key characteristics (or the begin() operation
+     * must fail with ErrorCode::INCOMPATIBLE_MGF_DIGEST).
+     *
+     * If the caller does not specify an MGF1 digest in the params argument of begin(), a default
+     * MGF1 digest of SHA1 is used.  If the key characteristics have any explicitly specified values
+     * for RSA_OAEP_MGF_DIGEST, then SHA1 must be included (or the begin() operation must fail with
+     * ErrorCode::INCOMPATIBLE_MGF_DIGEST).
      *
      * Must be hardware-enforced.
      */
@@ -268,25 +274,10 @@
     USAGE_EXPIRE_DATETIME = TagType.DATE | 402,
 
     /**
-     * Tag::MIN_SECONDS_BETWEEN_OPS specifies the minimum amount of time that elapses between
-     * allowed operations using a key.  This can be used to rate-limit uses of keys in contexts
-     * where unlimited use may enable brute force attacks.
+     * OBSOLETE: Do not use.
      *
-     * The value is a 32-bit integer representing seconds between allowed operations.
-     *
-     * When a key with this tag is used in an operation, the IKeyMintDevice must start a timer
-     * during the finish() or abort() call.  Any call to begin() that is received before the timer
-     * indicates that the interval specified by Tag::MIN_SECONDS_BETWEEN_OPS has elapsed must fail
-     * with ErrorCode::KEY_RATE_LIMIT_EXCEEDED.  This implies that the IKeyMintDevice must keep a
-     * table of use counters for keys with this tag.  Because memory is often limited, this table
-     * may have a fixed maximum size and KeyMint may fail operations that attempt to use keys with
-     * this tag when the table is full.  The table must accommodate at least 8 in-use keys and
-     * aggressively reuse table slots when key minimum-usage intervals expire.  If an operation
-     * fails because the table is full, KeyMint returns ErrorCode::TOO_MANY_OPERATIONS.
-     *
-     * Must be hardware-enforced.
-     *
-     * TODO(b/191738660): Remove in KeyMint V2. Currently only used for FDE.
+     * This tag value is included for historical reason, as it was present in Keymaster.
+     * KeyMint implementations do not need to support this tag.
      */
     MIN_SECONDS_BETWEEN_OPS = TagType.UINT | 403,
 
@@ -504,7 +495,9 @@
      * that is necessary during all uses of the key.  In particular, calls to exportKey() and
      * getKeyCharacteristics() must provide the same value to the clientId parameter, and calls to
      * begin() must provide this tag and the same associated data as part of the inParams set.  If
-     * the correct data is not provided, the method must return ErrorCode::INVALID_KEY_BLOB.
+     * the correct data is not provided, the method must return ErrorCode::INVALID_KEY_BLOB.  Note
+     * that a key with a zero-length APPLICATION_ID cannot have its key characteristics retrieved
+     * using getKeyCharacteristics() due to a historical limitation of the API.
      *
      * The content of this tag must be bound to the key cryptographically, meaning it must not be
      * possible for an adversary who has access to all of the secure world secrets but does not have
@@ -525,7 +518,9 @@
      * that is necessary during all uses of the key.  In particular, calls to begin() and
      * exportKey() must provide the same value to the appData parameter, and calls to begin must
      * provide this tag and the same associated data as part of the inParams set.  If the correct
-     * data is not provided, the method must return ErrorCode::INVALID_KEY_BLOB.
+     * data is not provided, the method must return ErrorCode::INVALID_KEY_BLOB.  Note that a key
+     * with a zero-length APPLICATION_DATA cannot have its key characteristics retrieved using
+     * getKeyCharacteristics() due to a historical limitation of the API.
      *
      * The content of this tag must be bound to the key cryptographically, meaning it must not be
      * possible for an adversary who has access to all of the secure world secrets but does not have
@@ -888,8 +883,12 @@
     STORAGE_KEY = TagType.BOOL | 722,
 
     /**
-     * OBSOLETE: Do not use. See IKeyMintOperation.updateAad instead.
-     * TODO(b/191738660): Remove in KeyMint v2.
+     * OBSOLETE: Do not use.
+     *
+     * This tag value is included for historical reasons -- in Keymaster it was used to hold
+     * associated data for AEAD encryption, as an additional parameter to
+     * IKeymasterDevice::finish().  In KeyMint the IKeyMintOperation::updateAad() method is used for
+     * this.
      */
     ASSOCIATED_DATA = TagType.BYTES | 1000,
 
@@ -928,10 +927,12 @@
     RESET_SINCE_ID_ROTATION = TagType.BOOL | 1004,
 
     /**
-     * OBSOLETE: Do not use. See the authToken parameter for IKeyMintDevice::begin and for
-     * IKeyMintOperation methods instead.
+     * OBSOLETE: Do not use.
      *
-     * TODO(b/191738660): Delete when keystore1 is deleted.
+     * This tag value is included for historical reasons -- in Keymaster it was used to hold
+     * a confirmation token as an additional parameter to
+     * IKeymasterDevice::finish().  In KeyMint the IKeyMintOperation::finish() method includes
+     * a confirmationToken argument for this.
      */
     CONFIRMATION_TOKEN = TagType.BYTES | 1005,
 
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 46db4f0..5473062 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -772,6 +772,100 @@
     }
 }
 
+void KeyMintAidlTestBase::AesCheckEncryptOneByteAtATime(const string& key, BlockMode block_mode,
+                                                        PaddingMode padding_mode, const string& iv,
+                                                        const string& plaintext,
+                                                        const string& exp_cipher_text) {
+    bool is_authenticated_cipher = (block_mode == BlockMode::GCM);
+    auto auth_set = AuthorizationSetBuilder()
+                            .Authorization(TAG_NO_AUTH_REQUIRED)
+                            .AesEncryptionKey(key.size() * 8)
+                            .BlockMode(block_mode)
+                            .Padding(padding_mode);
+    if (iv.size() > 0) auth_set.Authorization(TAG_CALLER_NONCE);
+    if (is_authenticated_cipher) auth_set.Authorization(TAG_MIN_MAC_LENGTH, 128);
+    ASSERT_EQ(ErrorCode::OK, ImportKey(auth_set, KeyFormat::RAW, key));
+
+    CheckEncryptOneByteAtATime(block_mode, 16 /*block_size*/, padding_mode, iv, plaintext,
+                               exp_cipher_text);
+}
+
+void KeyMintAidlTestBase::CheckEncryptOneByteAtATime(BlockMode block_mode, const int block_size,
+                                                     PaddingMode padding_mode, const string& iv,
+                                                     const string& plaintext,
+                                                     const string& exp_cipher_text) {
+    bool is_stream_cipher = (block_mode == BlockMode::CTR || block_mode == BlockMode::GCM);
+    bool is_authenticated_cipher = (block_mode == BlockMode::GCM);
+    auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding_mode);
+    if (iv.size() > 0) params.Authorization(TAG_NONCE, iv.data(), iv.size());
+    if (is_authenticated_cipher) params.Authorization(TAG_MAC_LENGTH, 128);
+
+    AuthorizationSet output_params;
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
+
+    string actual_ciphertext;
+    if (is_stream_cipher) {
+        // Assert that a 1 byte of output is produced for 1 byte of input.
+        // Every input byte produces an output byte.
+        for (int plaintext_index = 0; plaintext_index < plaintext.size(); plaintext_index++) {
+            string ciphertext;
+            EXPECT_EQ(ErrorCode::OK, Update(plaintext.substr(plaintext_index, 1), &ciphertext));
+            // Some StrongBox implementations cannot support 1:1 input:output lengths, so
+            // we relax this API restriction for them.
+            if (SecLevel() != SecurityLevel::STRONGBOX) {
+                EXPECT_EQ(1, ciphertext.size()) << "plaintext index: " << plaintext_index;
+            }
+            actual_ciphertext.append(ciphertext);
+        }
+        string ciphertext;
+        EXPECT_EQ(ErrorCode::OK, Finish(&ciphertext));
+        if (SecLevel() != SecurityLevel::STRONGBOX) {
+            string expected_final_output;
+            if (is_authenticated_cipher) {
+                expected_final_output = exp_cipher_text.substr(plaintext.size());
+            }
+            EXPECT_EQ(expected_final_output, ciphertext);
+        }
+        actual_ciphertext.append(ciphertext);
+    } else {
+        // Assert that a block of output is produced once a full block of input is provided.
+        // Every input block produces an output block.
+        bool compare_output = true;
+        string additional_information;
+        int vendor_api_level = property_get_int32("ro.vendor.api_level", 0);
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            // This is known to be broken on older vendor implementations.
+            if (vendor_api_level < 33) {
+                compare_output = false;
+            } else {
+                additional_information = " (b/194134359) ";
+            }
+        }
+        for (int plaintext_index = 0; plaintext_index < plaintext.size(); plaintext_index++) {
+            string ciphertext;
+            EXPECT_EQ(ErrorCode::OK, Update(plaintext.substr(plaintext_index, 1), &ciphertext));
+            if (compare_output) {
+                if ((plaintext_index % block_size) == block_size - 1) {
+                    // Update is expected to have output a new block
+                    EXPECT_EQ(block_size, ciphertext.size())
+                            << "plaintext index: " << plaintext_index << additional_information;
+                } else {
+                    // Update is expected to have produced no output
+                    EXPECT_EQ(0, ciphertext.size())
+                            << "plaintext index: " << plaintext_index << additional_information;
+                }
+            }
+            actual_ciphertext.append(ciphertext);
+        }
+        string ciphertext;
+        EXPECT_EQ(ErrorCode::OK, Finish(&ciphertext));
+        actual_ciphertext.append(ciphertext);
+    }
+    // Regardless of how the completed ciphertext got accumulated, it should match the expected
+    // ciphertext.
+    EXPECT_EQ(exp_cipher_text, actual_ciphertext);
+}
+
 void KeyMintAidlTestBase::CheckHmacTestVector(const string& key, const string& message,
                                               Digest digest, const string& expected_mac) {
     SCOPED_TRACE("CheckHmacTestVector");
@@ -976,12 +1070,24 @@
         return "Failure";
     }
     X509_Ptr key_cert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+    if (key_cert.get() == nullptr) {
+        ADD_FAILURE() << "Failed to parse cert";
+        return "Failure";
+    }
     EVP_PKEY_Ptr pub_key(X509_get_pubkey(key_cert.get()));
+    if (pub_key.get() == nullptr) {
+        ADD_FAILURE() << "Failed to retrieve public key";
+        return "Failure";
+    }
     RSA_Ptr rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(pub_key.get())));
+    if (rsa.get() == nullptr) {
+        ADD_FAILURE() << "Failed to retrieve RSA public key";
+        return "Failure";
+    }
 
     // Retrieve relevant tags.
     Digest digest = Digest::NONE;
-    Digest mgf_digest = Digest::NONE;
+    Digest mgf_digest = Digest::SHA1;
     PaddingMode padding = PaddingMode::NONE;
 
     auto digest_tag = params.GetTagValue(TAG_DIGEST);
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 8f9df24..67e8b21 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -188,6 +188,10 @@
 
     void CheckAesIncrementalEncryptOperation(BlockMode block_mode, int message_size);
 
+    void AesCheckEncryptOneByteAtATime(const string& key, BlockMode block_mode,
+                                       PaddingMode padding_mode, const string& iv,
+                                       const string& plaintext, const string& exp_cipher_text);
+
     void CheckHmacTestVector(const string& key, const string& message, Digest digest,
                              const string& expected_mac);
 
@@ -343,6 +347,11 @@
     string name_;
     string author_;
     long challenge_;
+
+  private:
+    void CheckEncryptOneByteAtATime(BlockMode block_mode, const int block_size,
+                                    PaddingMode padding_mode, const string& iv,
+                                    const string& plaintext, const string& exp_cipher_text);
 };
 
 // If the given property is available, add it to the tag set under the given tag ID.
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 4e746b2..4f5d821 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -613,7 +613,7 @@
 class NewKeyGenerationTest : public KeyMintAidlTestBase {
   protected:
     void CheckBaseParams(const vector<KeyCharacteristics>& keyCharacteristics) {
-        AuthorizationSet auths = CheckCommonParams(keyCharacteristics);
+        AuthorizationSet auths = CheckCommonParams(keyCharacteristics, KeyOrigin::GENERATED);
         EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::SIGN));
 
         // Check that some unexpected tags/values are NOT present.
@@ -622,20 +622,21 @@
     }
 
     void CheckSymmetricParams(const vector<KeyCharacteristics>& keyCharacteristics) {
-        AuthorizationSet auths = CheckCommonParams(keyCharacteristics);
+        AuthorizationSet auths = CheckCommonParams(keyCharacteristics, KeyOrigin::GENERATED);
         EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::ENCRYPT));
         EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::DECRYPT));
 
         EXPECT_FALSE(auths.Contains(TAG_PURPOSE, KeyPurpose::SIGN));
     }
 
-    AuthorizationSet CheckCommonParams(const vector<KeyCharacteristics>& keyCharacteristics) {
+    AuthorizationSet CheckCommonParams(const vector<KeyCharacteristics>& keyCharacteristics,
+                                       const KeyOrigin expectedKeyOrigin) {
         // TODO(swillden): Distinguish which params should be in which auth list.
         AuthorizationSet auths;
         for (auto& entry : keyCharacteristics) {
             auths.push_back(AuthorizationSet(entry.authorizations));
         }
-        EXPECT_TRUE(auths.Contains(TAG_ORIGIN, KeyOrigin::GENERATED));
+        EXPECT_TRUE(auths.Contains(TAG_ORIGIN, expectedKeyOrigin));
 
         // Verify that App data, ROT and auth timeout are NOT included.
         EXPECT_FALSE(auths.Contains(TAG_ROOT_OF_TRUST));
@@ -740,6 +741,7 @@
 
     for (auto block_mode : ValidBlockModes(Algorithm::AES)) {
         for (auto padding_mode : ValidPaddingModes(Algorithm::AES, block_mode)) {
+            SCOPED_TRACE(testing::Message() << "AES-unknown-" << block_mode << "-" << padding_mode);
             vector<uint8_t> key_blob;
             vector<KeyCharacteristics> key_characteristics;
             // No key size specified
@@ -993,6 +995,7 @@
  */
 TEST_P(NewKeyGenerationTest, Rsa) {
     for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+        SCOPED_TRACE(testing::Message() << "RSA-" << key_size);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@@ -1065,6 +1068,7 @@
     vector<uint8_t> serial_blob(build_serial_blob(serial_int));
 
     for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+        SCOPED_TRACE(testing::Message() << "RSA-" << key_size);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         auto builder = AuthorizationSetBuilder()
@@ -1102,9 +1106,9 @@
                 << "Key size " << key_size << "missing";
         EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
 
+        ASSERT_GT(cert_chain_.size(), 0);
         verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
-        ASSERT_GT(cert_chain_.size(), 0);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
@@ -1147,6 +1151,7 @@
     attestation_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
 
     for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+        SCOPED_TRACE(testing::Message() << "RSA-" << key_size);
         auto challenge = "hello";
         auto app_id = "foo";
 
@@ -1178,6 +1183,7 @@
         EXPECT_FALSE(ChainSignaturesAreValid(cert_chain_));
 
         // The signature over the attested key should correspond to the P256 public key.
+        ASSERT_GT(cert_chain_.size(), 0);
         X509_Ptr key_cert(parse_cert_blob(cert_chain_[0].encodedCertificate));
         ASSERT_TRUE(key_cert.get());
         EVP_PKEY_Ptr signing_pubkey;
@@ -1265,9 +1271,9 @@
             << "Key size " << key_size << "missing";
     EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
 
+    ASSERT_GT(cert_chain_.size(), 0);
     verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
     EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
-    ASSERT_GT(cert_chain_.size(), 0);
 
     AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
     AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
@@ -1293,6 +1299,7 @@
     vector<uint8_t> serial_blob(build_serial_blob(serial_int));
 
     for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+        SCOPED_TRACE(testing::Message() << "RSA-" << key_size);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK,
@@ -1317,9 +1324,9 @@
                 << "Key size " << key_size << "missing";
         EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
 
+        ASSERT_EQ(cert_chain_.size(), 1);
         verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
-        ASSERT_EQ(cert_chain_.size(), 1);
 
         CheckedDeleteKey(&key_blob);
     }
@@ -1398,6 +1405,7 @@
             << "Key size " << key_size << "missing";
     EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
 
+    ASSERT_GT(cert_chain_.size(), 0);
     verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
     EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
     ASSERT_EQ(cert_chain_.size(), 1);
@@ -1413,6 +1421,7 @@
  */
 TEST_P(NewKeyGenerationTest, LimitedUsageRsa) {
     for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+        SCOPED_TRACE(testing::Message() << "RSA-" << key_size);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@@ -1463,6 +1472,7 @@
     vector<uint8_t> serial_blob(build_serial_blob(serial_int));
 
     for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+        SCOPED_TRACE(testing::Message() << "RSA-" << key_size);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         auto builder = AuthorizationSetBuilder()
@@ -1532,6 +1542,7 @@
  */
 TEST_P(NewKeyGenerationTest, NoInvalidRsaSizes) {
     for (auto key_size : InvalidKeySizes(Algorithm::RSA)) {
+        SCOPED_TRACE(testing::Message() << "RSA-" << key_size);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
@@ -1566,6 +1577,7 @@
  */
 TEST_P(NewKeyGenerationTest, RsaMissingParams) {
     for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+        SCOPED_TRACE(testing::Message() << "RSA-" << key_size);
         ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(
                           AuthorizationSetBuilder().RsaKey(key_size, 65537).SetDefaultValidity()));
@@ -1581,6 +1593,7 @@
  */
 TEST_P(NewKeyGenerationTest, Ecdsa) {
     for (auto curve : ValidCurves()) {
+        SCOPED_TRACE(testing::Message() << "Curve::" << curve);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@@ -1706,6 +1719,7 @@
     vector<uint8_t> serial_blob(build_serial_blob(serial_int));
 
     for (auto curve : ValidCurves()) {
+        SCOPED_TRACE(testing::Message() << "Curve::" << curve);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         auto builder = AuthorizationSetBuilder()
@@ -2208,6 +2222,7 @@
     vector<uint8_t> serial_blob(build_serial_blob(serial_int));
 
     for (auto curve : ValidCurves()) {
+        SCOPED_TRACE(testing::Message() << "Curve::" << curve);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK,
@@ -2228,8 +2243,8 @@
         EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
 
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
-        verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
         ASSERT_EQ(cert_chain_.size(), 1);
+        verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
@@ -2279,6 +2294,7 @@
     auto app_id = "foo";
 
     for (auto curve : ValidCurves()) {
+        SCOPED_TRACE(testing::Message() << "Curve::" << curve);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@@ -2320,6 +2336,7 @@
     std::vector<uint32_t> app_id_lengths{143, 258};
 
     for (uint32_t length : app_id_lengths) {
+        SCOPED_TRACE(testing::Message() << "app_id_len=" << length);
         const string app_id(length, 'a');
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
@@ -2374,6 +2391,7 @@
  */
 TEST_P(NewKeyGenerationTest, LimitedUsageEcdsa) {
     for (auto curve : ValidCurves()) {
+        SCOPED_TRACE(testing::Message() << "Curve::" << curve);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@@ -2427,6 +2445,7 @@
  */
 TEST_P(NewKeyGenerationTest, EcdsaInvalidCurve) {
     for (auto curve : InvalidCurves()) {
+        SCOPED_TRACE(testing::Message() << "Curve::" << curve);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         auto result = GenerateKey(AuthorizationSetBuilder()
@@ -2448,6 +2467,29 @@
 }
 
 /*
+ * NewKeyGenerationTest.EcdsaMissingCurve
+ *
+ * Verifies that EC key generation fails if EC_CURVE not specified after KeyMint V2.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaMissingCurve) {
+    if (AidlVersion() < 2) {
+        /*
+         * The KeyMint V1 spec required that EC_CURVE be specified for EC keys.
+         * However, this was not checked at the time so we can only be strict about checking this
+         * for implementations of KeyMint version 2 and above.
+         */
+        GTEST_SKIP() << "Requiring EC_CURVE only strict since KeyMint v2";
+    }
+    /* If EC_CURVE not provided, generateKey
+     * must return ErrorCode::UNSUPPORTED_KEY_SIZE or ErrorCode::UNSUPPORTED_EC_CURVE.
+     */
+    auto result = GenerateKey(
+            AuthorizationSetBuilder().EcdsaKey(256).Digest(Digest::NONE).SetDefaultValidity());
+    ASSERT_TRUE(result == ErrorCode::UNSUPPORTED_KEY_SIZE ||
+                result == ErrorCode::UNSUPPORTED_EC_CURVE);
+}
+
+/*
  * NewKeyGenerationTest.EcdsaMismatchKeySize
  *
  * Verifies that specifying mismatched key size and curve for EC key generation returns
@@ -2481,6 +2523,7 @@
         digest = Digest::SHA_2_512;
     }
     for (auto curve : ValidCurves()) {
+        SCOPED_TRACE(testing::Message() << "Curve::" << curve);
         EXPECT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                      .EcdsaSigningKey(curve)
                                                      .Digest(digest)
@@ -2498,6 +2541,7 @@
  */
 TEST_P(NewKeyGenerationTest, Hmac) {
     for (auto digest : ValidDigests(false /* withNone */, true /* withMD5 */)) {
+        SCOPED_TRACE(testing::Message() << "Digest::" << digest);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         constexpr size_t key_size = 128;
@@ -2531,6 +2575,7 @@
     auto app_id = "foo";
 
     for (auto digest : ValidDigests(false /* withNone */, true /* withMD5 */)) {
+        SCOPED_TRACE(testing::Message() << "Digest::" << digest);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         constexpr size_t key_size = 128;
@@ -2564,6 +2609,7 @@
  */
 TEST_P(NewKeyGenerationTest, LimitedUsageHmac) {
     for (auto digest : ValidDigests(false /* withNone */, true /* withMD5 */)) {
+        SCOPED_TRACE(testing::Message() << "Digest::" << digest);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         constexpr size_t key_size = 128;
@@ -2602,6 +2648,7 @@
  */
 TEST_P(NewKeyGenerationTest, HmacCheckKeySizes) {
     for (size_t key_size = 0; key_size <= 512; ++key_size) {
+        SCOPED_TRACE(testing::Message() << "HMAC-" << key_size);
         if (key_size < 64 || key_size % 8 != 0) {
             // To keep this test from being very slow, we only test a random fraction of
             // non-byte key sizes.  We test only ~10% of such cases. Since there are 392 of
@@ -2644,6 +2691,7 @@
  */
 TEST_P(NewKeyGenerationTest, HmacCheckMinMacLengths) {
     for (size_t min_mac_length = 0; min_mac_length <= 256; ++min_mac_length) {
+        SCOPED_TRACE(testing::Message() << "MIN_MAC_LENGTH=" << min_mac_length);
         if (min_mac_length < 64 || min_mac_length % 8 != 0) {
             // To keep this test from being very long, we only test a random fraction of
             // non-byte lengths.  We test only ~10% of such cases. Since there are 172 of them,
@@ -2800,6 +2848,7 @@
     for (auto padding :
          {PaddingMode::NONE, PaddingMode::RSA_PSS, PaddingMode::RSA_PKCS1_1_5_SIGN}) {
         for (auto digest : ValidDigests(true /* withNone */, true /* withMD5 */)) {
+            SCOPED_TRACE(testing::Message() << "RSA padding=" << padding << " digest=" << digest);
             if (padding == PaddingMode::NONE && digest != Digest::NONE) {
                 // Digesting only makes sense with padding.
                 continue;
@@ -3515,6 +3564,7 @@
  */
 TEST_P(SigningOperationsTest, HmacAllDigests) {
     for (auto digest : ValidDigests(false /* withNone */, false /* withMD5 */)) {
+        SCOPED_TRACE(testing::Message() << "Digest::" << digest);
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                      .Authorization(TAG_NO_AUTH_REQUIRED)
                                                      .HmacKey(128)
@@ -3776,7 +3826,7 @@
 // TODO(seleneh) add ExportKey to GenerateKey
 // check result
 
-class ImportKeyTest : public KeyMintAidlTestBase {
+class ImportKeyTest : public NewKeyGenerationTest {
   public:
     template <TagType tag_type, Tag tag, typename ValueT>
     void CheckCryptoParam(TypedTag<tag_type, tag> ttag, ValueT expected) {
@@ -4365,6 +4415,7 @@
     string key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
     uint32_t bitlen = key.size() * 8;
     for (uint32_t key_size : {bitlen - 1, bitlen + 1, bitlen - 8, bitlen + 8}) {
+        SCOPED_TRACE(testing::Message() << "import-key-size=" << key_size);
         // Explicit key size doesn't match that of the provided key.
         auto result = ImportKey(AuthorizationSetBuilder()
                                         .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -4432,6 +4483,7 @@
     string key = hex2str("a49d7564199e97cb529d2c9d97bf2f98d35edf57ba1f7358");
     uint32_t bitlen = key.size() * 7;
     for (uint32_t key_size : {bitlen - 1, bitlen + 1, bitlen - 8, bitlen + 8}) {
+        SCOPED_TRACE(testing::Message() << "import-key-size=" << key_size);
         // Explicit key size doesn't match that of the provided key.
         auto result = ImportKey(AuthorizationSetBuilder()
                                         .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -4486,6 +4538,65 @@
     VerifyMessage(message, signature, AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
 }
 
+/*
+ * ImportKeyTest.GetKeyCharacteristics
+ *
+ * Verifies that imported keys have the correct characteristics.
+ */
+TEST_P(ImportKeyTest, GetKeyCharacteristics) {
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+    auto base_builder = AuthorizationSetBuilder()
+                                .Padding(PaddingMode::NONE)
+                                .Authorization(TAG_NO_AUTH_REQUIRED)
+                                .SetDefaultValidity();
+    vector<Algorithm> algorithms = {Algorithm::RSA, Algorithm::EC, Algorithm::HMAC, Algorithm::AES,
+                                    Algorithm::TRIPLE_DES};
+    ErrorCode result;
+    string symKey = hex2str("a49d7564199e97cb529d2c9d97bf2f98");                   // 128 bits
+    string tdesKey = hex2str("a49d7564199e97cb529d2c9d97bf2f98d35edf57ba1f7358");  // 192 bits
+    for (auto alg : algorithms) {
+        SCOPED_TRACE(testing::Message() << "Algorithm-" << alg);
+        AuthorizationSetBuilder builder(base_builder);
+        switch (alg) {
+            case Algorithm::RSA:
+                builder.RsaSigningKey(2048, 65537).Digest(Digest::NONE);
+
+                result = ImportKey(builder, KeyFormat::PKCS8, rsa_2048_key, &key_blob,
+                                   &key_characteristics);
+                break;
+            case Algorithm::EC:
+                builder.EcdsaSigningKey(EcCurve::P_256).Digest(Digest::NONE);
+                result = ImportKey(builder, KeyFormat::PKCS8, ec_256_key, &key_blob,
+                                   &key_characteristics);
+                break;
+            case Algorithm::HMAC:
+                builder.HmacKey(128)
+                        .Digest(Digest::SHA_2_256)
+                        .Authorization(TAG_MIN_MAC_LENGTH, 128);
+                result =
+                        ImportKey(builder, KeyFormat::RAW, symKey, &key_blob, &key_characteristics);
+                break;
+            case Algorithm::AES:
+                builder.AesEncryptionKey(128).BlockMode(BlockMode::ECB);
+                result =
+                        ImportKey(builder, KeyFormat::RAW, symKey, &key_blob, &key_characteristics);
+                break;
+            case Algorithm::TRIPLE_DES:
+                builder.TripleDesEncryptionKey(168).BlockMode(BlockMode::ECB);
+                result = ImportKey(builder, KeyFormat::RAW, tdesKey, &key_blob,
+                                   &key_characteristics);
+                break;
+            default:
+                ADD_FAILURE() << "Invalid Algorithm " << uint32_t(alg);
+                continue;
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
+        CheckCharacteristics(key_blob, key_characteristics);
+        CheckCommonParams(key_characteristics, KeyOrigin::IMPORTED);
+    }
+}
+
 INSTANTIATE_KEYMINT_AIDL_TEST(ImportKeyTest);
 
 auto wrapped_key = hex2str(
@@ -4858,6 +4969,7 @@
  */
 TEST_P(EncryptionOperationsTest, RsaNoPaddingSuccess) {
     for (uint64_t exponent : ValidExponents()) {
+        SCOPED_TRACE(testing::Message() << "RSA exponent=" << exponent);
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                      .Authorization(TAG_NO_AUTH_REQUIRED)
                                                      .RsaEncryptionKey(2048, exponent)
@@ -5048,6 +5160,7 @@
     string message = "Hello";
 
     for (auto digest : digests) {
+        SCOPED_TRACE(testing::Message() << "digest-" << digest);
         auto params = AuthorizationSetBuilder()
                               .Authorization(TAG_RSA_OAEP_MGF_DIGEST, digest)
                               .Digest(Digest::SHA_2_256)
@@ -5084,6 +5197,79 @@
 }
 
 /*
+ * EncryptionOperationsTest.RsaOaepMGFDigestDefaultSuccess
+ *
+ * Verifies that RSA-OAEP decryption operations work when no MGF digest is
+ * specified, defaulting to SHA-1.
+ */
+TEST_P(EncryptionOperationsTest, RsaOaepMGFDigestDefaultSuccess) {
+    size_t key_size = 2048;
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .RsaEncryptionKey(key_size, 65537)
+                                                 .Padding(PaddingMode::RSA_OAEP)
+                                                 .Digest(Digest::SHA_2_256)
+                                                 .SetDefaultValidity()));
+
+    // Do local RSA encryption using the default MGF digest of SHA-1.
+    string message = "Hello";
+    auto params =
+            AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::RSA_OAEP);
+    string ciphertext = LocalRsaEncryptMessage(message, params);
+    EXPECT_EQ(key_size / 8, ciphertext.size());
+
+    // Do KeyMint RSA decryption also using the default MGF digest of SHA-1.
+    string plaintext = DecryptMessage(ciphertext, params);
+    EXPECT_EQ(message, plaintext) << "RSA-OAEP failed with default digest";
+
+    // Decrypting corrupted ciphertext should fail.
+    size_t offset_to_corrupt = random() % ciphertext.size();
+    char corrupt_byte;
+    do {
+        corrupt_byte = static_cast<char>(random() % 256);
+    } while (corrupt_byte == ciphertext[offset_to_corrupt]);
+    ciphertext[offset_to_corrupt] = corrupt_byte;
+
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+    string result;
+    EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext, &result));
+    EXPECT_EQ(0U, result.size());
+}
+
+/*
+ * EncryptionOperationsTest.RsaOaepMGFDigestDefaultFail
+ *
+ * Verifies that RSA-OAEP decryption operations fail when no MGF digest is
+ * specified on begin (thus defaulting to SHA-1), but the key characteristics
+ * has an explicit set of values for MGF_DIGEST that do not contain SHA-1.
+ */
+TEST_P(EncryptionOperationsTest, RsaOaepMGFDigestDefaultFail) {
+    size_t key_size = 2048;
+    ASSERT_EQ(ErrorCode::OK,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .Authorization(TAG_NO_AUTH_REQUIRED)
+                                  .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_256)
+                                  .RsaEncryptionKey(key_size, 65537)
+                                  .Padding(PaddingMode::RSA_OAEP)
+                                  .Digest(Digest::SHA_2_256)
+                                  .SetDefaultValidity()));
+
+    // Do local RSA encryption using the default MGF digest of SHA-1.
+    string message = "Hello";
+    auto params =
+            AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::RSA_OAEP);
+    string ciphertext = LocalRsaEncryptMessage(message, params);
+    EXPECT_EQ(key_size / 8, ciphertext.size());
+
+    // begin() params do not include MGF_DIGEST, so a default of SHA1 is assumed.
+    // Key characteristics *do* include values for MGF_DIGEST, so the SHA1 value
+    // is checked against those values, and found absent.
+    auto result = Begin(KeyPurpose::DECRYPT, params);
+    EXPECT_TRUE(result == ErrorCode::UNSUPPORTED_MGF_DIGEST ||
+                result == ErrorCode::INCOMPATIBLE_MGF_DIGEST);
+}
+
+/*
  * EncryptionOperationsTest.RsaOaepWithMGFIncompatibleDigest
  *
  * Verifies that RSA-OAEP decryption operations fail in the correct way when asked to operate
@@ -5395,6 +5581,7 @@
  */
 TEST_P(EncryptionOperationsTest, AesEcbCbcNoPaddingWrongInputSize) {
     for (BlockMode blockMode : {BlockMode::ECB, BlockMode::CBC}) {
+        SCOPED_TRACE(testing::Message() << "AES-" << blockMode);
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                      .Authorization(TAG_NO_AUTH_REQUIRED)
                                                      .AesEncryptionKey(128)
@@ -5614,6 +5801,328 @@
     CheckAesIncrementalEncryptOperation(BlockMode::GCM, 240);
 }
 
+/*
+ * EncryptionOperationsTest.Aes128CBCNoPaddingOneByteAtATime
+ * Verifies input and output sizes of AES/CBC/NoPadding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes128CBCNoPaddingOneByteAtATime) {
+    string kat_key = hex2str("7E3D723C09A9852B24F584F9D916F6A8");
+    string kat_iv = hex2str("944AE274D983892EADE422274858A96A");
+    string kat_plaintext =
+            hex2str("044E15899A080AADEB6778F64323B64D2CBCBADB338DF93B9AC459D4F41029"
+                    "809FFF37081C22EF278F896AB213A2A631");
+    string kat_ciphertext =
+            hex2str("B419293FCBD686F2913D1CF947E510D42FAFEDE5593C98AFD6AEE272596A"
+                    "56FE42C22F2A5E3B6A02BA9D8D0DE1E9A810");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::CBC, PaddingMode::NONE, kat_iv, kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes128CBCPKCS7PaddingOneByteAtATime
+ * Verifies input and output sizes of AES/CBC/PKCS7Padding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes128CBCPKCS7PaddingOneByteAtATime) {
+    string kat_key = hex2str("F16E698472578E919D92806262C5169F");
+    string kat_iv = hex2str("EF743540F8421ACA128A3247521F3E7D");
+    string kat_plaintext =
+            hex2str("5BEBF33569D90BF5E853814E12E7C7AA5758013F755773E29F4A25EC26EEB7"
+                    "65F7F2DC251F7DC62AEFCA1E8A5A11A1DCD44F0BD8FB593A5AE3");
+    string kat_ciphertext =
+            hex2str("3197CF6DB9466188B5FED375329324EE7D6092A8C0E41DFAF49E3724271427"
+                    "896D56A6243C0D59D6639722AF93CD53449BDDABF9C5F153EBDBFED9ED98C8CC37");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::CBC, PaddingMode::PKCS7, kat_iv,
+                                  kat_plaintext, kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes128CTRNoPaddingOneByteAtATime
+ * Verifies input and output sizes of AES/CTR/NoPadding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes128CTRNoPaddingOneByteAtATime) {
+    string kat_key = hex2str("4713a7b2f93efe809b42ecc45213ef9f");
+    string kat_iv = hex2str("ebfa19b0ebf3d57feabd4c4bd04bea01");
+    string kat_plaintext =
+            hex2str("6d2c07e1fc86f99c6e2a8f6567828b4262a9c23d0f3ed8ab32482283c79796"
+                    "f0adba1bcd3736084996452a917fae98005aebe61f9e91c3");
+    string kat_ciphertext =
+            hex2str("345deb1d67b95e600e05cad4c32ec381aadb3e2c1ec7e0fb956dc38e6860cf"
+                    "0553535566e1b12fa9f87d29266ca26df427233df035df28");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::CTR, PaddingMode::NONE, kat_iv, kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes128ECBNoPaddingOneByteAtATime
+ * Verifies input and output sizes of AES/ECB/NoPadding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes128ECBNoPaddingOneByteAtATime) {
+    string kat_key = hex2str("7DA2467F068854B3CB36E5C333A16619");
+    string kat_plaintext =
+            hex2str("9A07C9575AD9CE209DF9F3953965CEBE8208587C7AE575A1904BF25048946D"
+                    "7B6168A9A27BCE554BEA94EF26E6C742A0");
+    string kat_ciphertext =
+            hex2str("8C47E49420FC92AC4CA2C601BC3F8AC31D01B260B7B849F2B8EEDFFFED8F36"
+                    "C31CBDA0D22F95C9C2A48C347E8C77AC82");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::ECB, PaddingMode::NONE, "", kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes128ECBPKCS7PaddingOneByteAtATime
+ * Verifies input and output sizes of AES/ECB/PKCS7Padding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes128ECBPKCS7PaddingOneByteAtATime) {
+    string kat_key = hex2str("C3BE04BCCB3D99B85290F113FE7AF194");
+    string kat_plaintext =
+            hex2str("348C213FD8DF3F990C20C5ACBF07B34B6264AE245784A5A6176DBFB1C2E7DD"
+                    "27E52CC92B8EEE40614F05B507B355F6354A2705BD86");
+    string kat_ciphertext =
+            hex2str("07CD05C41FEDEDDC5DB4B3E35E676153184A119AA4DFDDC290616F1FA60093"
+                    "1DE6BEA9BDB90D1D733899946F8C8E5C0C4383F99F5D88E27F3EBC0C6E52759ED3");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::ECB, PaddingMode::PKCS7, "", kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes128GCMNoPaddingOneByteAtATime
+ * Verifies input and output sizes of AES/GCM/NoPadding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes128GCMNoPaddingOneByteAtATime) {
+    string kat_key = hex2str("ba76354f0aed6e8d91f45c4ff5a062db");
+    string kat_iv = hex2str("b79437ae08ff355d7d8a4d0f");
+    string kat_plaintext =
+            hex2str("6d7596a8fd56ceaec61de7940984b7736fec44f572afc3c8952e4dc6541e2b"
+                    "c6a702c440a37610989543f63fedb047ca2173bc18581944");
+    string kat_ciphertext =
+            hex2str("b3f6799e8f9326f2df1e80fcd2cb16d78c9dc7cc14bb677862dc6c639b3a63"
+                    "38d24b312d3989e5920b5dbfc976765efbfe57bb385940a7a43bdf05bddae3c9d6a2fb"
+                    "bdfcc0cba0");
+
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::GCM, PaddingMode::NONE, kat_iv, kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes192CBCNoPaddingOneByteAtATime
+ * Verifies input and output sizes of AES/CBC/NoPadding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes192CBCNoPaddingOneByteAtATime) {
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Key size 192 is not supported by Strongbox.";
+    }
+    string kat_key = hex2str("be8cc4e25cce46e5d55725e2391f7d3cf59ed60062f5a43b");
+    string kat_iv = hex2str("80a199aab0eee77e7762ddf3b3a32f40");
+    string kat_plaintext =
+            hex2str("064f9200e0df37d4711af4a69d11addf9e1c345d9d8195f9f1f715019ce96a"
+                    "167f2497c994bd496eb80bfb2ba2c9d5af");
+    string kat_ciphertext =
+            hex2str("859b90becaa85e95a71e104efbd7a3b723bcbf4eb39865544a05d9e90b6fe5"
+                    "72c134552f3a138e726fbe493b3a839598");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::CBC, PaddingMode::NONE, kat_iv, kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes192CBCPKCS7PaddingOneByteAtATime
+ * Verifies input and output sizes of AES/CBC/PKCS7Padding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes192CBCPKCS7PaddingOneByteAtATime) {
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Key size 192 is not supported by Strongbox.";
+    }
+    string kat_key = hex2str("68969215ec41e4df7d23de0e806f458f52aff492bd7c5263");
+    string kat_iv = hex2str("e61d13dfbf0533289f0e7950209da418");
+    string kat_plaintext =
+            hex2str("8d4c1cac27511ee2d82409a7f378e7e402b0eb189c1eaa5c506eb72a9074"
+                    "b170");
+    string kat_ciphertext =
+            hex2str("e70bcd62c595dc1b2b8c197bb91a7447e1be2cbcf3fdc69e7e991faf0f57cf"
+                    "4e3884138ff403a41fd99818708ada301c");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::CBC, PaddingMode::PKCS7, kat_iv,
+                                  kat_plaintext, kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes192CTRNoPaddingOneByteAtATime
+ * Verifies input and output sizes of AES/CTR/NoPadding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes192CTRNoPaddingOneByteAtATime) {
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Key size 192 is not supported by Strongbox.";
+    }
+    string kat_key = hex2str("5e2036e790d38815c90beb67a1c9e5aa0e167ef082927317");
+    string kat_iv = hex2str("df0694959b89054156962d68a226965c");
+    string kat_plaintext =
+            hex2str("6ed2781c99e03e45314d6019932220c2c98130c53f9f67ad10ac519adf50e9"
+                    "28091e09cdbbd3b42b");
+    string kat_ciphertext =
+            hex2str("e427b6666502e05b82d0b20ae50e862b1936d71266fc49178ac984e71571f2"
+                    "2ae0f90f0c19f42b4a");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::CTR, PaddingMode::NONE, kat_iv, kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes192ECBNoPaddingOneByteAtATime
+ * Verifies input and output sizes of AES/ECB/NoPadding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes192ECBNoPaddingOneByteAtATime) {
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Key size 192 is not supported by Strongbox.";
+    }
+    string kat_key = hex2str("3cab83fb338ba985fbfe74c5e9d2e900adb570b1d67faf92");
+    string kat_plaintext =
+            hex2str("2cc64c335a13fb838f3c6aad0a6b47297ca90bb886ddb059200f0b41740c"
+                    "44ab");
+    string kat_ciphertext =
+            hex2str("9c5c825328f5ee0aa24947e374d3f9165f484b39dd808c790d7a12964810"
+                    "2453");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::ECB, PaddingMode::NONE, "", kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes192ECBPKCS7PaddingOneByteAtATime
+ * Verifies input and output sizes of AES/ECB/PKCS7Padding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes192ECBPKCS7PaddingOneByteAtATime) {
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Key size 192 is not supported by Strongbox.";
+    }
+    string kat_key = hex2str("d57f4e5446f736c16476ec4db5decc7b1bf3936e4f7e4618");
+    string kat_plaintext =
+            hex2str("b115777f1ee7a43a07daa6401e59c46b7a98213a8747eabfbe3ca4ec93524d"
+                    "e2c7");
+    string kat_ciphertext =
+            hex2str("1e92cd20da08bb5fa174a7a69879d4fc25a155e6af06d75b26c5b450d273c8"
+                    "bb7e3a889dd4a9589098b44acf1056e7aa");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::ECB, PaddingMode::PKCS7, "", kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes192GCMNoPaddingOneByteAtATime
+ * Verifies input and output sizes of AES/GCM/NoPadding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes192GCMNoPaddingOneByteAtATime) {
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Key size 192 is not supported by Strongbox.";
+    }
+    string kat_key = hex2str("21339fc1d011abca65d50ce2365230603fd47d07e8830f6e");
+    string kat_iv = hex2str("d5fb1469a8d81dd75286a418");
+    string kat_plaintext =
+            hex2str("cf776dedf53a828d51a0073db3ef0dd1ee19e2e9e243ce97e95841bb9ad4e3"
+                    "ff52");
+    string kat_ciphertext =
+            hex2str("3a0d48278111d3296bc663df8a5dbeb2474ea47fd85b608f8d9375d9dcf7de"
+                    "1413ad70fb0e1970669095ad77ebb5974ae8");
+
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::GCM, PaddingMode::NONE, kat_iv, kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes256CBCNoPaddingOneByteAtATime
+ * Verifies input and output sizes of AES/CBC/NoPadding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes256CBCNoPaddingOneByteAtATime) {
+    string kat_key = hex2str("dd2f20dc6b98c100bac919120ff95eb5d96003f8229987b283a1e777b0cd5c30");
+    string kat_iv = hex2str("23b4d85239fb90db93b07a981e90a170");
+    string kat_plaintext =
+            hex2str("2fbe5d46dca5cea433e550d8b291740ab9551c2a2d37680d7fb7b993225f58"
+                    "494cb53caca353e4b637ba05687be20f8d");
+    string kat_ciphertext =
+            hex2str("5aba24fc316936c8369061ee8fe463e4faed04288e204456626b988c0e376b"
+                    "6047da1e4fd7c4e1cf2656097f75ae8685");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::CBC, PaddingMode::NONE, kat_iv, kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes256CBCPKCS7PaddingOneByteAtATime
+ * Verifies input and output sizes of AES/CBC/PKCS7Padding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes256CBCPKCS7PaddingOneByteAtATime) {
+    string kat_key = hex2str("03ab2510520f5cfebfab0a17a7f8324c9634911f6fc59e586f85346bb38ac88a");
+    string kat_iv = hex2str("9af96967195bb0184f129beffa8241ae");
+    string kat_plaintext =
+            hex2str("2d6944653ac14988a772a2730b7c5bfa99a21732ae26f40cdc5b3a2874c794"
+                    "2545a82b73c48078b9dae62261c65909");
+    string kat_ciphertext =
+            hex2str("26b308f7e1668b55705a79c8b3ad10e244655f705f027f390a5c34e4536f51"
+                    "9403a71987b95124073d69f2a3cb95b0ab");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::CBC, PaddingMode::PKCS7, kat_iv,
+                                  kat_plaintext, kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes256CTRNoPaddingOneByteAtATime
+ * Verifies input and output sizes of AES/CTR/NoPadding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes256CTRNoPaddingOneByteAtATime) {
+    string kat_key = hex2str("928b380a8fed4b4b4cfeb56e0c66a4cb0f9ff58d61ac68bcfd0e3fbd910a684f");
+    string kat_iv = hex2str("0b678a5249e6eeda461dfb4776b6c58e");
+    string kat_plaintext =
+            hex2str("f358de57543b297e997cba46fb9100553d6abd65377e55b9aac3006400ead1"
+                    "1f6db3c884");
+    string kat_ciphertext =
+            hex2str("a07a35fbd1776ad81462e1935f542337add60962bf289249476817b6ddd532"
+                    "a7be30d4c3");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::CTR, PaddingMode::NONE, kat_iv, kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes256ECBNoPaddingOneByteAtATime
+ * Verifies input and output sizes of AES/ECB/NoPadding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes256ECBNoPaddingOneByteAtATime) {
+    string kat_key = hex2str("fa4622d9cf6485075daedd33d2c4fffdf859e2edb7f7df4f04603f7e647fae90");
+    string kat_plaintext =
+            hex2str("96ccabbe0c68970d8cdee2b30ab43c2d61cc50ee68271e77571e72478d713a"
+                    "31a476d6806b8116089c6ec50bb543200f");
+    string kat_ciphertext =
+            hex2str("0e81839e9dfbfe3b503d619e676abe5ac80fac3f245d8f09b9134b1b32a67d"
+                    "c83e377faf246288931136bef2a07c0be4");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::ECB, PaddingMode::NONE, "", kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes256ECBPKCS7PaddingOneByteAtATime
+ * Verifies input and output sizes of AES/ECB/PKCS7Padding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes256ECBPKCS7PaddingOneByteAtATime) {
+    string kat_key = hex2str("bf3f07c68467fead0ca8e2754500ab514258abf02eb7e615a493bcaaa45d5ee1");
+    string kat_plaintext =
+            hex2str("af0757e49018dad628f16998628a407db5f28291bef3bc2e4d8a5a31fb238e"
+                    "6f");
+    string kat_ciphertext =
+            hex2str("21ec3011074bf1ef140643d47130326c5e183f61237c69bc77551ca207d71f"
+                    "c2b90cfac6c8d2d125e5cd9ff353dee0df");
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::ECB, PaddingMode::PKCS7, "", kat_plaintext,
+                                  kat_ciphertext);
+}
+
+/*
+ * EncryptionOperationsTest.Aes256GCMNoPaddingOneByteAtATime
+ * Verifies input and output sizes of AES/GCM/NoPadding Algorithm.
+ */
+TEST_P(EncryptionOperationsTest, Aes256GCMNoPaddingOneByteAtATime) {
+    string kat_key = hex2str("7972140d831eedac75d5ea515c9a4c3bb124499a90b5f317ac1a685e88fae395");
+    string kat_iv = hex2str("a66c5252808d823dd4151fed");
+    string kat_plaintext =
+            hex2str("c2b9dabf3a55adaa94e8c0d1e77a84a3435aee23b2c3c4abb587b09a9c2afb"
+                    "f0");
+    string kat_ciphertext =
+            hex2str("a960619314657b2afb96b93bebb372bffd09e19d53e351f17d1ba2611f9dc3"
+                    "3c9c92d563e8fd381254ac262aa2a4ea0d");
+
+    AesCheckEncryptOneByteAtATime(kat_key, BlockMode::GCM, PaddingMode::NONE, kat_iv, kat_plaintext,
+                                  kat_ciphertext);
+}
+
 struct AesCtrSp80038aTestVector {
     const char* key;
     const char* nonce;
@@ -5769,6 +6278,7 @@
     // Zero input message
     string message = "";
     for (auto padding : {PaddingMode::NONE, PaddingMode::PKCS7}) {
+        SCOPED_TRACE(testing::Message() << "AES padding=" << padding);
         auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(padding);
         AuthorizationSet out_params;
         string ciphertext1 = EncryptMessage(message, params, &out_params);
@@ -6163,7 +6673,7 @@
 
     // Encrypt
     AuthorizationSet begin_out_params;
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
     string ciphertext;
     AuthorizationSet finish_out_params;
     ASSERT_EQ(ErrorCode::OK, UpdateAad(aad));
@@ -6206,7 +6716,7 @@
                                 .Authorization(TAG_MAC_LENGTH, tag_bits);
     AuthorizationSet begin_out_params;
 
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
 
     // No data, AAD only.
     EXPECT_EQ(ErrorCode::OK, UpdateAad("foo"));
@@ -6222,7 +6732,7 @@
     begin_params.push_back(begin_out_params);
 
     // Decrypt
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
     EXPECT_EQ(ErrorCode::OK, UpdateAad("foofoo"));
     string plaintext;
     EXPECT_EQ(ErrorCode::OK, Finish(ciphertext, &plaintext));
@@ -6249,7 +6759,7 @@
                                 .Authorization(TAG_MAC_LENGTH, 128);
     AuthorizationSet begin_out_params;
 
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
 
     EXPECT_EQ(ErrorCode::OK, UpdateAad("foo"));
     string ciphertext;
@@ -6283,7 +6793,7 @@
 
     // Encrypt
     AuthorizationSet begin_out_params;
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
     EXPECT_EQ(ErrorCode::OK, UpdateAad("foobar"));
     string ciphertext;
     EXPECT_EQ(ErrorCode::OK, Finish(message, &ciphertext));
@@ -6292,7 +6802,7 @@
     begin_params.push_back(begin_out_params);
 
     // Decrypt.
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params, &begin_out_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params, &begin_out_params));
     EXPECT_EQ(ErrorCode::OK, UpdateAad("barfoo"));
     string plaintext;
     EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(ciphertext, &plaintext));
@@ -6319,7 +6829,7 @@
 
     // Encrypt
     AuthorizationSet begin_out_params;
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
     EXPECT_EQ(ErrorCode::OK, UpdateAad("foobar"));
     string ciphertext;
     AuthorizationSet finish_out_params;
@@ -6329,7 +6839,7 @@
     begin_params.push_back(TAG_NONCE, AidlBuf("123456789012"));
 
     // Decrypt.
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params, &begin_out_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params, &begin_out_params));
     EXPECT_EQ(ErrorCode::OK, UpdateAad("foobar"));
     string plaintext;
     EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(ciphertext, &plaintext));
@@ -6361,7 +6871,7 @@
 
     // Encrypt
     AuthorizationSet begin_out_params;
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
     EXPECT_EQ(ErrorCode::OK, UpdateAad(aad));
     string ciphertext;
     EXPECT_EQ(ErrorCode::OK, Finish(message, &ciphertext));
@@ -6373,7 +6883,7 @@
     params.push_back(begin_out_params);
 
     // Decrypt.
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
     EXPECT_EQ(ErrorCode::OK, UpdateAad(aad));
     string plaintext;
     EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(ciphertext, &plaintext));
@@ -6437,6 +6947,7 @@
                                                  .Padding(PaddingMode::PKCS7)));
 
     for (size_t i = 0; i < 32; ++i) {
+        SCOPED_TRACE(testing::Message() << "msg size=" << i);
         string message(i, 'a');
         auto inParams =
                 AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
@@ -6486,7 +6997,7 @@
     for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
         ++ciphertext[ciphertext.size() / 2];
 
-        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
         string plaintext;
         EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext));
         ErrorCode error = Finish(&plaintext);
@@ -6747,6 +7258,7 @@
  */
 TEST_P(EncryptionOperationsTest, TripleDesEcbCbcNoPaddingWrongInputSize) {
     for (BlockMode blockMode : {BlockMode::ECB, BlockMode::CBC}) {
+        SCOPED_TRACE(testing::Message() << "BlockMode::" << blockMode);
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                      .TripleDesEncryptionKey(168)
                                                      .BlockMode(blockMode)
@@ -6758,7 +7270,7 @@
         auto begin_params =
                 AuthorizationSetBuilder().BlockMode(blockMode).Padding(PaddingMode::NONE);
         AuthorizationSet output_params;
-        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &output_params));
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &output_params));
         string ciphertext;
         EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, "", &ciphertext));
 
@@ -6805,6 +7317,7 @@
 
     // Try various message lengths; all should fail.
     for (size_t i = 0; i <= 32; i++) {
+        SCOPED_TRACE(testing::Message() << "i = " << i);
         auto begin_params =
                 AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::PKCS7);
         EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, begin_params));
@@ -6837,7 +7350,7 @@
     for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
         SCOPED_TRACE(testing::Message() << "i = " << i);
         ++ciphertext[ciphertext.size() / 2];
-        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
         string plaintext;
         EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext));
         ErrorCode error = Finish(&plaintext);
@@ -6869,7 +7382,7 @@
     AuthorizationSet input_params =
             AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
     AuthorizationSet output_params;
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, input_params, &output_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, input_params, &output_params));
 
     string ciphertext;
     for (size_t i = 0; i < message.size(); i += increment)
@@ -6883,7 +7396,7 @@
     input_params.push_back(TAG_PADDING, PaddingMode::NONE);
     output_params.Clear();
 
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, input_params, &output_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, input_params, &output_params));
     string plaintext;
     for (size_t i = 0; i < ciphertext.size(); i += increment)
         EXPECT_EQ(ErrorCode::OK, Update(ciphertext.substr(i, increment), &plaintext));
@@ -7000,7 +7513,7 @@
     } else {
         // Usage count limit tag is enforced by keystore, keymint does nothing.
         EXPECT_TRUE(keystore_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U));
-        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
     }
 }
 
@@ -7047,7 +7560,7 @@
     } else {
         // Usage count limit tag is enforced by keystore, keymint does nothing.
         EXPECT_TRUE(keystore_auths.Contains(TAG_USAGE_COUNT_LIMIT, 3U));
-        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
     }
 }
 
@@ -7093,7 +7606,7 @@
     } else {
         // Usage count limit tag is enforced by keystore, keymint does nothing.
         EXPECT_TRUE(keystore_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U));
-        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, params));
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, params));
     }
 }
 
@@ -7140,7 +7653,7 @@
     } else {
         // Usage count limit tag is enforced by keystore, keymint does nothing.
         EXPECT_TRUE(keystore_auths.Contains(TAG_USAGE_COUNT_LIMIT, 3U));
-        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, params));
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, params));
     }
 }
 
@@ -7453,7 +7966,7 @@
         EXPECT_EQ(ErrorCode::OK, Abort(op_handles[j]))
                 << "Aboort failed for i = " << j << std::endl;
     }
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
     AbortIfNeeded();
 }
 
@@ -7474,11 +7987,12 @@
                                                  .Padding(PaddingMode::NONE)));
 
     for (int msg_size = 8 /* 256 bytes */; msg_size <= 11 /* 2 KiB */; msg_size++) {
+        SCOPED_TRACE(testing::Message() << "msg_size = " << msg_size);
         auto cipher_params =
                 AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
 
         AuthorizationSet out_params;
-        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, cipher_params, &out_params));
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, cipher_params, &out_params));
 
         string plain_message = std::string(1 << msg_size, 'x');
         string encrypted_message;
@@ -7489,7 +8003,7 @@
                 << "Encrypt finish returned OK, but did not consume all of the given input";
         cipher_params.push_back(out_params);
 
-        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, cipher_params));
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, cipher_params));
 
         string decrypted_message;
         rc = Finish(encrypted_message, &decrypted_message);
@@ -7655,7 +8169,7 @@
             if (curve != localCurve) {
                 // If the keys are using different curves KeyMint should fail with
                 // ErrorCode:INVALID_ARGUMENT. Check that.
-                EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
+                ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
                 string ZabFromKeyMintStr;
                 EXPECT_EQ(ErrorCode::INVALID_ARGUMENT,
                           Finish(string(localPublicKey.begin(), localPublicKey.end()),
@@ -7787,6 +8301,7 @@
     GenerateKeyMintEcKey(curve, &kmPubKey);
 
     for (auto localCurve : ValidCurves()) {
+        SCOPED_TRACE(testing::Message() << "local-curve-" << localCurve);
         if (localCurve == curve) {
             continue;
         }
@@ -7795,7 +8310,7 @@
         vector<uint8_t> encodedPublicKey;
         GenerateLocalEcKey(localCurve, &privKey, &encodedPublicKey);
 
-        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
         string ZabFromKeyMintStr;
         EXPECT_EQ(ErrorCode::INVALID_ARGUMENT,
                   Finish(string(encodedPublicKey.begin(), encodedPublicKey.end()),
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 7184613..4f361bb 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <memory>
+#include <string>
 #define LOG_TAG "VtsRemotelyProvisionableComponentTests"
 
 #include <AndroidRemotelyProvisionedComponentDevice.h>
@@ -30,6 +32,7 @@
 #include <openssl/ec_key.h>
 #include <openssl/x509.h>
 #include <remote_prov/remote_prov_utils.h>
+#include <optional>
 #include <set>
 #include <vector>
 
@@ -43,6 +46,7 @@
 namespace {
 
 constexpr int32_t VERSION_WITH_UNIQUE_ID_SUPPORT = 2;
+constexpr int32_t VERSION_WITHOUT_TEST_MODE = 3;
 
 #define INSTANTIATE_REM_PROV_AIDL_TEST(name)                                         \
     GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name);                             \
@@ -57,22 +61,6 @@
 using namespace remote_prov;
 using namespace keymaster;
 
-std::set<std::string> getAllowedVbStates() {
-    return {"green", "yellow", "orange"};
-}
-
-std::set<std::string> getAllowedBootloaderStates() {
-    return {"locked", "unlocked"};
-}
-
-std::set<std::string> getAllowedSecurityLevels() {
-    return {"tee", "strongbox"};
-}
-
-std::set<std::string> getAllowedAttIdStates() {
-    return {"locked", "open"};
-}
-
 bytevec string_to_bytevec(const char* s) {
     const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
     return bytevec(p, p + strlen(s));
@@ -193,6 +181,15 @@
         return params;
     }
 
+    void checkMacedPubkeyVersioned(const MacedPublicKey& macedPubKey, bool testMode,
+                                   vector<uint8_t>* payload_value) {
+        if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
+            check_maced_pubkey(macedPubKey, false, payload_value);
+        } else {
+            check_maced_pubkey(macedPubKey, testMode, payload_value);
+        }
+    }
+
   protected:
     std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
     RpcHardwareInfo rpcHardwareInfo;
@@ -213,9 +210,7 @@
         RpcHardwareInfo hwInfo;
         ASSERT_TRUE(rpc->getHardwareInfo(&hwInfo).isOk());
 
-        int32_t version;
-        ASSERT_TRUE(rpc->getInterfaceVersion(&version).isOk());
-        if (version >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
+        if (hwInfo.versionNumber >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
             ASSERT_TRUE(hwInfo.uniqueId);
             auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
             EXPECT_TRUE(wasInserted);
@@ -245,10 +240,7 @@
  * Verify that the unique id is within the length limits as described in RpcHardwareInfo.aidl.
  */
 TEST_P(GetHardwareInfoTests, uniqueId) {
-    int32_t version;
-    ASSERT_TRUE(provisionable_->getInterfaceVersion(&version).isOk());
-
-    if (version < VERSION_WITH_UNIQUE_ID_SUPPORT) {
+    if (rpcHardwareInfo.versionNumber < VERSION_WITH_UNIQUE_ID_SUPPORT) {
         return;
     }
 
@@ -274,7 +266,7 @@
     auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
     ASSERT_TRUE(status.isOk());
     vector<uint8_t> coseKeyData;
-    check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
+    checkMacedPubkeyVersioned(macedPubKey, testMode, &coseKeyData);
 }
 
 /**
@@ -297,7 +289,7 @@
     auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
     ASSERT_TRUE(status.isOk());
     vector<uint8_t> coseKeyData;
-    check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
+    checkMacedPubkeyVersioned(macedPubKey, testMode, &coseKeyData);
 
     AttestationKey attestKey;
     attestKey.keyBlob = std::move(privateKeyBlob);
@@ -352,13 +344,13 @@
     bool testMode = true;
     auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
     ASSERT_TRUE(status.isOk());
-
-    check_maced_pubkey(macedPubKey, testMode, nullptr);
+    checkMacedPubkeyVersioned(macedPubKey, testMode, nullptr);
 }
 
-class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
+class CertificateRequestTestBase : public VtsRemotelyProvisionedComponentTests {
   protected:
-    CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
+    CertificateRequestTestBase()
+        : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
 
     void generateTestEekChain(size_t eekLength) {
         auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
@@ -377,162 +369,11 @@
             ASSERT_TRUE(status.isOk()) << status.getMessage();
 
             vector<uint8_t> payload_value;
-            check_maced_pubkey(key, testMode, &payload_value);
+            checkMacedPubkeyVersioned(key, testMode, &payload_value);
             cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
         }
     }
 
-    ErrMsgOr<bytevec> getSessionKey(ErrMsgOr<std::pair<bytevec, bytevec>>& senderPubkey) {
-        if (rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_25519 ||
-            rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_NONE) {
-            return x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
-                                         senderPubkey->first, false /* senderIsA */);
-        } else {
-            return ECDH_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
-                                       senderPubkey->first, false /* senderIsA */);
-        }
-    }
-
-    void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
-                            const bytevec& keysToSignMac, const ProtectedData& protectedData,
-                            std::vector<BccEntryData>* bccOutput = nullptr) {
-        auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
-        ASSERT_TRUE(parsedProtectedData) << protDataErrMsg;
-        ASSERT_TRUE(parsedProtectedData->asArray());
-        ASSERT_EQ(parsedProtectedData->asArray()->size(), kCoseEncryptEntryCount);
-
-        auto senderPubkey = getSenderPubKeyFromCoseEncrypt(parsedProtectedData);
-        ASSERT_TRUE(senderPubkey) << senderPubkey.message();
-        EXPECT_EQ(senderPubkey->second, eekId_);
-
-        auto sessionKey = getSessionKey(senderPubkey);
-        ASSERT_TRUE(sessionKey) << sessionKey.message();
-
-        auto protectedDataPayload =
-                decryptCoseEncrypt(*sessionKey, parsedProtectedData.get(), bytevec{} /* aad */);
-        ASSERT_TRUE(protectedDataPayload) << protectedDataPayload.message();
-
-        auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
-        ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg;
-        ASSERT_TRUE(parsedPayload->asArray());
-        // Strongbox may contain additional certificate chain.
-        EXPECT_LE(parsedPayload->asArray()->size(), 3U);
-
-        auto& signedMac = parsedPayload->asArray()->get(0);
-        auto& bcc = parsedPayload->asArray()->get(1);
-        ASSERT_TRUE(signedMac && signedMac->asArray());
-        ASSERT_TRUE(bcc && bcc->asArray());
-
-        // BCC is [ pubkey, + BccEntry]
-        auto bccContents = validateBcc(bcc->asArray());
-        ASSERT_TRUE(bccContents) << "\n" << bccContents.message() << "\n" << prettyPrint(bcc.get());
-        ASSERT_GT(bccContents->size(), 0U);
-
-        auto [deviceInfoMap, __2, deviceInfoErrMsg] = cppbor::parse(deviceInfo.deviceInfo);
-        ASSERT_TRUE(deviceInfoMap) << "Failed to parse deviceInfo: " << deviceInfoErrMsg;
-        ASSERT_TRUE(deviceInfoMap->asMap());
-        checkDeviceInfo(deviceInfoMap->asMap(), deviceInfo.deviceInfo);
-        auto& signingKey = bccContents->back().pubKey;
-        deviceInfoMap->asMap()->canonicalize();
-        auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
-                                              cppbor::Array()  // SignedMacAad
-                                                      .add(challenge_)
-                                                      .add(std::move(deviceInfoMap))
-                                                      .add(keysToSignMac)
-                                                      .encode());
-        ASSERT_TRUE(macKey) << macKey.message();
-
-        auto coseMac0 = cppbor::Array()
-                                .add(cppbor::Map()  // protected
-                                             .add(ALGORITHM, HMAC_256)
-                                             .canonicalize()
-                                             .encode())
-                                .add(cppbor::Map())        // unprotected
-                                .add(keysToSign.encode())  // payload (keysToSign)
-                                .add(keysToSignMac);       // tag
-
-        auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
-        ASSERT_TRUE(macPayload) << macPayload.message();
-
-        if (bccOutput) {
-            *bccOutput = std::move(*bccContents);
-        }
-    }
-
-    void checkType(const cppbor::Map* devInfo, uint8_t majorType, std::string entryName) {
-        const auto& val = devInfo->get(entryName);
-        ASSERT_TRUE(val) << entryName << " does not exist";
-        ASSERT_EQ(val->type(), majorType) << entryName << " has the wrong type.";
-        switch (majorType) {
-            case cppbor::TSTR:
-                EXPECT_GT(val->asTstr()->value().size(), 0);
-                break;
-            case cppbor::BSTR:
-                EXPECT_GT(val->asBstr()->value().size(), 0);
-                break;
-            default:
-                break;
-        }
-    }
-
-    void checkDeviceInfo(const cppbor::Map* deviceInfo, bytevec deviceInfoBytes) {
-        EXPECT_EQ(deviceInfo->clone()->asMap()->canonicalize().encode(), deviceInfoBytes)
-                << "DeviceInfo ordering is non-canonical.";
-        const auto& version = deviceInfo->get("version");
-        ASSERT_TRUE(version);
-        ASSERT_TRUE(version->asUint());
-        RpcHardwareInfo info;
-        provisionable_->getHardwareInfo(&info);
-        ASSERT_EQ(version->asUint()->value(), info.versionNumber);
-        std::set<std::string> allowList;
-        switch (version->asUint()->value()) {
-            // These fields became mandated in version 2.
-            case 2:
-                checkType(deviceInfo, cppbor::TSTR, "brand");
-                checkType(deviceInfo, cppbor::TSTR, "manufacturer");
-                checkType(deviceInfo, cppbor::TSTR, "product");
-                checkType(deviceInfo, cppbor::TSTR, "model");
-                checkType(deviceInfo, cppbor::TSTR, "device");
-                // TODO: Refactor the KeyMint code that validates these fields and include it here.
-                checkType(deviceInfo, cppbor::TSTR, "vb_state");
-                allowList = getAllowedVbStates();
-                EXPECT_NE(allowList.find(deviceInfo->get("vb_state")->asTstr()->value()),
-                          allowList.end());
-                checkType(deviceInfo, cppbor::TSTR, "bootloader_state");
-                allowList = getAllowedBootloaderStates();
-                EXPECT_NE(allowList.find(deviceInfo->get("bootloader_state")->asTstr()->value()),
-                          allowList.end());
-                checkType(deviceInfo, cppbor::BSTR, "vbmeta_digest");
-                checkType(deviceInfo, cppbor::UINT, "system_patch_level");
-                checkType(deviceInfo, cppbor::UINT, "boot_patch_level");
-                checkType(deviceInfo, cppbor::UINT, "vendor_patch_level");
-                checkType(deviceInfo, cppbor::UINT, "fused");
-                EXPECT_LT(deviceInfo->get("fused")->asUint()->value(), 2);  // Must be 0 or 1.
-                checkType(deviceInfo, cppbor::TSTR, "security_level");
-                allowList = getAllowedSecurityLevels();
-                EXPECT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
-                          allowList.end());
-                if (deviceInfo->get("security_level")->asTstr()->value() == "tee") {
-                    checkType(deviceInfo, cppbor::TSTR, "os_version");
-                }
-                break;
-            case 1:
-                checkType(deviceInfo, cppbor::TSTR, "security_level");
-                allowList = getAllowedSecurityLevels();
-                EXPECT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
-                          allowList.end());
-                if (version->asUint()->value() == 1) {
-                    checkType(deviceInfo, cppbor::TSTR, "att_id_state");
-                    allowList = getAllowedAttIdStates();
-                    EXPECT_NE(allowList.find(deviceInfo->get("att_id_state")->asTstr()->value()),
-                              allowList.end());
-                }
-                break;
-            default:
-                FAIL() << "Unrecognized version: " << version->asUint()->value();
-        }
-    }
-
     bytevec eekId_;
     size_t testEekLength_;
     EekChain testEekChain_;
@@ -541,6 +382,18 @@
     cppbor::Array cborKeysToSign_;
 };
 
+class CertificateRequestTest : public CertificateRequestTestBase {
+  protected:
+    void SetUp() override {
+        CertificateRequestTestBase::SetUp();
+
+        if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
+            GTEST_SKIP() << "This test case only applies to RKP v1 and v2. "
+                         << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
+        }
+    }
+};
+
 /**
  * Generate an empty certificate request in test mode, and decrypt and verify the structure and
  * content.
@@ -559,7 +412,10 @@
                 &protectedData, &keysToSignMac);
         ASSERT_TRUE(status.isOk()) << status.getMessage();
 
-        checkProtectedData(deviceInfo, cppbor::Array(), keysToSignMac, protectedData);
+        auto result = verifyProductionProtectedData(
+                deviceInfo, cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_,
+                rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+        ASSERT_TRUE(result) << result.message();
     }
 }
 
@@ -581,22 +437,24 @@
             &protectedData, &keysToSignMac);
     ASSERT_TRUE(status.isOk()) << status.getMessage();
 
-    std::vector<BccEntryData> firstBcc;
-    checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
-                       &firstBcc);
+    auto firstBcc = verifyProductionProtectedData(
+            deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
+            eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+    ASSERT_TRUE(firstBcc) << firstBcc.message();
 
     status = provisionable_->generateCertificateRequest(
             testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
             &protectedData, &keysToSignMac);
     ASSERT_TRUE(status.isOk()) << status.getMessage();
 
-    std::vector<BccEntryData> secondBcc;
-    checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
-                       &secondBcc);
+    auto secondBcc = verifyProductionProtectedData(
+            deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
+            eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+    ASSERT_TRUE(secondBcc) << secondBcc.message();
 
     // Verify that none of the keys in the first BCC are repeated in the second one.
-    for (const auto& i : firstBcc) {
-        for (auto& j : secondBcc) {
+    for (const auto& i : *firstBcc) {
+        for (auto& j : *secondBcc) {
             ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
                     << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
         }
@@ -639,7 +497,10 @@
                 &keysToSignMac);
         ASSERT_TRUE(status.isOk()) << status.getMessage();
 
-        checkProtectedData(deviceInfo, cborKeysToSign_, keysToSignMac, protectedData);
+        auto result = verifyProductionProtectedData(
+                deviceInfo, cborKeysToSign_, keysToSignMac, protectedData, testEekChain_, eekId_,
+                rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+        ASSERT_TRUE(result) << result.message();
     }
 }
 
@@ -799,4 +660,131 @@
 
 INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
 
+class CertificateRequestV2Test : public CertificateRequestTestBase {
+    void SetUp() override {
+        CertificateRequestTestBase::SetUp();
+
+        if (rpcHardwareInfo.versionNumber < VERSION_WITHOUT_TEST_MODE) {
+            GTEST_SKIP() << "This test case only applies to RKP v3 and above. "
+                         << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
+        }
+    }
+};
+
+/**
+ * Generate an empty certificate request, and decrypt and verify the structure and content.
+ */
+TEST_P(CertificateRequestV2Test, EmptyRequest) {
+    bytevec csr;
+
+    auto status =
+            provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
+    ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+    auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_);
+    ASSERT_TRUE(result) << result.message();
+}
+
+/**
+ * Generate a non-empty certificate request.  Decrypt, parse and validate the contents.
+ */
+TEST_P(CertificateRequestV2Test, NonEmptyRequest) {
+    generateKeys(false /* testMode */, 1 /* numKeys */);
+
+    bytevec csr;
+
+    auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
+    ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+    auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
+    ASSERT_TRUE(result) << result.message();
+}
+
+/**
+ * Generate a non-empty certificate request.  Make sure contents are reproducible.
+ */
+TEST_P(CertificateRequestV2Test, NonEmptyRequestReproducible) {
+    generateKeys(false /* testMode */, 1 /* numKeys */);
+
+    bytevec csr;
+
+    auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
+    ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+    auto firstBcc = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
+    ASSERT_TRUE(firstBcc) << firstBcc.message();
+
+    status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
+    ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+    auto secondBcc = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
+    ASSERT_TRUE(secondBcc) << secondBcc.message();
+
+    ASSERT_EQ(firstBcc->size(), secondBcc->size());
+    for (auto i = 0; i < firstBcc->size(); i++) {
+        ASSERT_EQ(firstBcc->at(i).pubKey, secondBcc->at(i).pubKey);
+    }
+}
+
+/**
+ * Generate a non-empty certificate request with multiple keys.
+ */
+TEST_P(CertificateRequestV2Test, NonEmptyRequestMultipleKeys) {
+    // TODO(b/254137722): define a minimum number of keys that must be supported.
+    generateKeys(false /* testMode */, 5 /* numKeys */);
+
+    bytevec csr;
+
+    auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
+    ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+    auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
+    ASSERT_TRUE(result) << result.message();
+}
+
+/**
+ * Generate a non-empty certificate request, but with the MAC corrupted on the keypair.
+ */
+TEST_P(CertificateRequestV2Test, NonEmptyRequestCorruptMac) {
+    generateKeys(false /* testMode */, 1 /* numKeys */);
+    auto result = corrupt_maced_key(keysToSign_[0]);
+    ASSERT_TRUE(result) << result.moveMessage();
+    MacedPublicKey keyWithCorruptMac = result.moveValue();
+
+    bytevec csr;
+    auto status =
+            provisionable_->generateCertificateRequestV2({keyWithCorruptMac}, challenge_, &csr);
+    ASSERT_FALSE(status.isOk()) << status.getMessage();
+    EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
+}
+
+/**
+ * Generate a non-empty certificate request in prod mode, with test keys.  Test mode must be
+ * ignored, i.e. test must pass.
+ */
+TEST_P(CertificateRequestV2Test, NonEmptyRequest_testKeyInProdCert) {
+    generateKeys(true /* testMode */, 1 /* numKeys */);
+
+    bytevec csr;
+    auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
+    ASSERT_TRUE(status.isOk()) << status.getMessage();
+}
+
+/**
+ * Call generateCertificateRequest(). Make sure it's removed.
+ */
+TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed) {
+    generateTestEekChain(2);
+    bytevec keysToSignMac;
+    DeviceInfo deviceInfo;
+    ProtectedData protectedData;
+    auto status = provisionable_->generateCertificateRequest(
+            true /* testMode */, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
+            &protectedData, &keysToSignMac);
+    ASSERT_FALSE(status.isOk()) << status.getMessage();
+    EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
+}
+
+INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);
+
 }  // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/performance/KeyMintBenchmark.cpp b/security/keymint/aidl/vts/performance/KeyMintBenchmark.cpp
index 54b6fdc..5bbae4c 100644
--- a/security/keymint/aidl/vts/performance/KeyMintBenchmark.cpp
+++ b/security/keymint/aidl/vts/performance/KeyMintBenchmark.cpp
@@ -142,6 +142,25 @@
         return Digest::NONE;
     }
 
+    optional<EcCurve> getCurveFromLength(int keySize) {
+        switch (keySize) {
+            case 224:
+                return EcCurve::P_224;
+                break;
+            case 256:
+                return EcCurve::P_256;
+                break;
+            case 384:
+                return EcCurve::P_384;
+                break;
+            case 521:
+                return EcCurve::P_521;
+                break;
+            default:
+                return {};
+        }
+    }
+
     bool GenerateKey(string transform, int keySize, bool sign = false) {
         if (transform == key_transform_) {
             return true;
@@ -184,6 +203,12 @@
         }
         if (algorithm == Algorithm::EC) {
             authSet.SetDefaultValidity();
+            std::optional<EcCurve> curve = getCurveFromLength(keySize);
+            if (!curve) {
+                std::cerr << "Error: invalid EC-Curve from size " << keySize << std::endl;
+                return false;
+            }
+            authSet.Authorization(TAG_EC_CURVE, curve.value());
         }
         error_ = GenerateKey(authSet);
         return error_ == ErrorCode::OK;
diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp
index bf2ab02..3f48320 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -65,6 +65,7 @@
     ],
     shared_libs: [
         "libbase",
+        "libbinder_ndk",
         "libcppbor_external",
         "libcppcose_rkp",
         "libcrypto",
diff --git a/security/keymint/support/include/remote_prov/remote_prov_utils.h b/security/keymint/support/include/remote_prov/remote_prov_utils.h
index f3b8608..6871e1b 100644
--- a/security/keymint/support/include/remote_prov/remote_prov_utils.h
+++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h
@@ -16,7 +16,9 @@
 
 #pragma once
 
+#include <memory>
 #include <vector>
+#include "aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h"
 
 #include <keymaster/cppcose/cppcose.h>
 
@@ -139,4 +141,55 @@
 JsonOutput jsonEncodeCsrWithBuild(const std::string instance_name,
                                   const cppbor::Array& csr);
 
+/**
+ * Parses a DeviceInfo structure from the given CBOR data. The parsed data is then validated to
+ * ensure it contains the minimum required data at the time of manufacturing. This is only a
+ * partial validation, as some fields may not be provisioned yet at the time this information
+ * is parsed in the manufacturing process.
+ */
+ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateFactoryDeviceInfo(
+        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable);
+
+/**
+ * Parses a DeviceInfo structure from the given CBOR data. The parsed data is then validated to
+ * ensure it is formatted correctly and that it contains the required values for Remote Key
+ * Provisioning. This is a full validation, and assumes the device is provisioned as if it is
+ * suitable for the end user.
+ */
+ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateProductionDeviceInfo(
+        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable);
+
+/**
+ * Verify the protected data as if the device is still early in the factory process and may not
+ * have all device identifiers provisioned yet.
+ */
+ErrMsgOr<std::vector<BccEntryData>> verifyFactoryProtectedData(
+        const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
+        const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
+        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+/**
+ * Verify the protected data as if the device is a final production sample.
+ */
+ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData(
+        const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
+        const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
+        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+
+/**
+ * Verify the CSR as if the device is still early in the factory process and may not
+ * have all device identifiers provisioned yet.
+ */
+ErrMsgOr<std::vector<BccEntryData>> verifyFactoryCsr(const cppbor::Array& keysToSign,
+                                                     const std::vector<uint8_t>& csr,
+                                                     IRemotelyProvisionedComponent* provisionable,
+                                                     const std::vector<uint8_t>& challenge);
+/**
+ * Verify the CSR as if the device is a final production sample.
+ */
+ErrMsgOr<std::vector<BccEntryData>> verifyProductionCsr(
+        const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
+        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+
 }  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 0dbea5b..f7ab3ac 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -15,7 +15,11 @@
  */
 
 #include <iterator>
+#include <memory>
+#include <set>
+#include <string>
 #include <tuple>
+#include "aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h"
 
 #include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
 #include <android-base/properties.h>
@@ -28,6 +32,7 @@
 #include <openssl/base64.h>
 #include <openssl/evp.h>
 #include <openssl/rand.h>
+#include <openssl/x509.h>
 #include <remote_prov/remote_prov_utils.h>
 
 namespace aidl::android::hardware::security::keymint::remote_prov {
@@ -41,6 +46,8 @@
 using EC_KEY_Ptr = bssl::UniquePtr<EC_KEY>;
 using EVP_PKEY_Ptr = bssl::UniquePtr<EVP_PKEY>;
 using EVP_PKEY_CTX_Ptr = bssl::UniquePtr<EVP_PKEY_CTX>;
+using X509_Ptr = bssl::UniquePtr<X509>;
+using CRYPTO_BUFFER_Ptr = bssl::UniquePtr<CRYPTO_BUFFER>;
 
 ErrMsgOr<bytevec> ecKeyGetPrivateKey(const EC_KEY* ecKey) {
     // Extract private key.
@@ -441,4 +448,558 @@
     return JsonOutput::Ok(Json::writeString(factory, json));
 }
 
+std::string checkMapEntry(bool isFactory, const cppbor::Map& devInfo, cppbor::MajorType majorType,
+                          const std::string& entryName) {
+    const std::unique_ptr<cppbor::Item>& val = devInfo.get(entryName);
+    if (!val) {
+        return entryName + " is missing.\n";
+    }
+    if (val->type() != majorType) {
+        return entryName + " has the wrong type.\n";
+    }
+    if (isFactory) {
+        return "";
+    }
+    switch (majorType) {
+        case cppbor::TSTR:
+            if (val->asTstr()->value().size() <= 0) {
+                return entryName + " is present but the value is empty.\n";
+            }
+            break;
+        case cppbor::BSTR:
+            if (val->asBstr()->value().size() <= 0) {
+                return entryName + " is present but the value is empty.\n";
+            }
+            break;
+        default:
+            break;
+    }
+    return "";
+}
+
+std::string checkMapEntry(bool isFactory, const cppbor::Map& devInfo, cppbor::MajorType majorType,
+                          const std::string& entryName, const cppbor::Array& allowList) {
+    std::string error = checkMapEntry(isFactory, devInfo, majorType, entryName);
+    if (!error.empty()) {
+        return error;
+    }
+
+    if (isFactory) {
+        return "";
+    }
+
+    const std::unique_ptr<cppbor::Item>& val = devInfo.get(entryName);
+    for (auto i = allowList.begin(); i != allowList.end(); ++i) {
+        if (**i == *val) {
+            return "";
+        }
+    }
+    return entryName + " has an invalid value.\n";
+}
+
+ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
+        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable,
+        bool isFactory) {
+    const cppbor::Array kValidVbStates = {"green", "yellow", "orange"};
+    const cppbor::Array kValidBootloaderStates = {"locked", "unlocked"};
+    const cppbor::Array kValidSecurityLevels = {"tee", "strongbox"};
+    const cppbor::Array kValidAttIdStates = {"locked", "open"};
+    const cppbor::Array kValidFused = {0, 1};
+
+    struct AttestationIdEntry {
+        const char* id;
+        bool alwaysValidate;
+    };
+    constexpr AttestationIdEntry kAttestationIdEntrySet[] = {{"brand", false},
+                                                             {"manufacturer", true},
+                                                             {"product", false},
+                                                             {"model", false},
+                                                             {"device", false}};
+
+    auto [parsedVerifiedDeviceInfo, ignore1, errMsg] = cppbor::parse(deviceInfoBytes);
+    if (!parsedVerifiedDeviceInfo) {
+        return errMsg;
+    }
+
+    std::unique_ptr<cppbor::Map> parsed(parsedVerifiedDeviceInfo->asMap());
+    if (!parsed) {
+        return "DeviceInfo must be a CBOR map.";
+    }
+    parsedVerifiedDeviceInfo.release();
+
+    if (parsed->clone()->asMap()->canonicalize().encode() != deviceInfoBytes) {
+        return "DeviceInfo ordering is non-canonical.";
+    }
+
+    RpcHardwareInfo info;
+    provisionable->getHardwareInfo(&info);
+    if (info.versionNumber < 3) {
+        const std::unique_ptr<cppbor::Item>& version = parsed->get("version");
+        if (!version) {
+            return "Device info is missing version";
+        }
+        if (!version->asUint()) {
+            return "version must be an unsigned integer";
+        }
+        if (version->asUint()->value() != info.versionNumber) {
+            return "DeviceInfo version (" + std::to_string(version->asUint()->value()) +
+                   ") does not match the remotely provisioned component version (" +
+                   std::to_string(info.versionNumber) + ").";
+        }
+    }
+
+    std::string error;
+    switch (info.versionNumber) {
+        case 3:
+        case 2:
+            for (const auto& entry : kAttestationIdEntrySet) {
+                error += checkMapEntry(isFactory && !entry.alwaysValidate, *parsed, cppbor::TSTR,
+                                       entry.id);
+            }
+            if (!error.empty()) {
+                return error +
+                       "Attestation IDs are missing or malprovisioned. If this test is being\n"
+                       "run against an early proto or EVT build, this error is probably WAI\n"
+                       "and indicates that Device IDs were not provisioned in the factory. If\n"
+                       "this error is returned on a DVT or later build revision, then\n"
+                       "something is likely wrong with the factory provisioning process.";
+            }
+            // TODO: Refactor the KeyMint code that validates these fields and include it here.
+            error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "vb_state", kValidVbStates);
+            error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "bootloader_state",
+                                   kValidBootloaderStates);
+            error += checkMapEntry(isFactory, *parsed, cppbor::BSTR, "vbmeta_digest");
+            error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "system_patch_level");
+            error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "boot_patch_level");
+            error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "vendor_patch_level");
+            error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "fused", kValidFused);
+            error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "security_level",
+                                   kValidSecurityLevels);
+            if (parsed->get("security_level") && parsed->get("security_level")->asTstr() &&
+                parsed->get("security_level")->asTstr()->value() == "tee") {
+                error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "os_version");
+            }
+            break;
+        case 1:
+            error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "security_level",
+                                   kValidSecurityLevels);
+            error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "att_id_state",
+                                   kValidAttIdStates);
+            break;
+        default:
+            return "Unrecognized version: " + std::to_string(info.versionNumber);
+    }
+
+    if (!error.empty()) {
+        return error;
+    }
+
+    return std::move(parsed);
+}
+
+ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateFactoryDeviceInfo(
+        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable) {
+    return parseAndValidateDeviceInfo(deviceInfoBytes, provisionable, /*isFactory=*/true);
+}
+
+ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateProductionDeviceInfo(
+        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable) {
+    return parseAndValidateDeviceInfo(deviceInfoBytes, provisionable, /*isFactory=*/false);
+}
+
+ErrMsgOr<bytevec> getSessionKey(ErrMsgOr<std::pair<bytevec, bytevec>>& senderPubkey,
+                                const EekChain& eekChain, int32_t supportedEekCurve) {
+    if (supportedEekCurve == RpcHardwareInfo::CURVE_25519 ||
+        supportedEekCurve == RpcHardwareInfo::CURVE_NONE) {
+        return x25519_HKDF_DeriveKey(eekChain.last_pubkey, eekChain.last_privkey,
+                                     senderPubkey->first, false /* senderIsA */);
+    } else {
+        return ECDH_HKDF_DeriveKey(eekChain.last_pubkey, eekChain.last_privkey, senderPubkey->first,
+                                   false /* senderIsA */);
+    }
+}
+
+ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData(
+        const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
+        const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
+        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
+        bool isFactory) {
+    auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
+    if (!parsedProtectedData) {
+        return protDataErrMsg;
+    }
+    if (!parsedProtectedData->asArray()) {
+        return "Protected data is not a CBOR array.";
+    }
+    if (parsedProtectedData->asArray()->size() != kCoseEncryptEntryCount) {
+        return "The protected data COSE_encrypt structure must have " +
+               std::to_string(kCoseEncryptEntryCount) + " entries, but it only has " +
+               std::to_string(parsedProtectedData->asArray()->size());
+    }
+
+    auto senderPubkey = getSenderPubKeyFromCoseEncrypt(parsedProtectedData);
+    if (!senderPubkey) {
+        return senderPubkey.message();
+    }
+    if (senderPubkey->second != eekId) {
+        return "The COSE_encrypt recipient does not match the expected EEK identifier";
+    }
+
+    auto sessionKey = getSessionKey(senderPubkey, eekChain, supportedEekCurve);
+    if (!sessionKey) {
+        return sessionKey.message();
+    }
+
+    auto protectedDataPayload =
+            decryptCoseEncrypt(*sessionKey, parsedProtectedData.get(), bytevec{} /* aad */);
+    if (!protectedDataPayload) {
+        return protectedDataPayload.message();
+    }
+
+    auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
+    if (!parsedPayload) {
+        return "Failed to parse payload: " + payloadErrMsg;
+    }
+    if (!parsedPayload->asArray()) {
+        return "The protected data payload must be an Array.";
+    }
+    if (parsedPayload->asArray()->size() != 3U && parsedPayload->asArray()->size() != 2U) {
+        return "The protected data payload must contain SignedMAC and BCC. It may optionally "
+               "contain AdditionalDKSignatures. However, the parsed payload has " +
+               std::to_string(parsedPayload->asArray()->size()) + " entries.";
+    }
+
+    auto& signedMac = parsedPayload->asArray()->get(0);
+    auto& bcc = parsedPayload->asArray()->get(1);
+    if (!signedMac->asArray()) {
+        return "The SignedMAC in the protected data payload is not an Array.";
+    }
+    if (!bcc->asArray()) {
+        return "The BCC in the protected data payload is not an Array.";
+    }
+
+    // BCC is [ pubkey, + BccEntry]
+    auto bccContents = validateBcc(bcc->asArray());
+    if (!bccContents) {
+        return bccContents.message() + "\n" + prettyPrint(bcc.get());
+    }
+    if (bccContents->size() == 0U) {
+        return "The BCC is empty. It must contain at least one entry.";
+    }
+
+    auto deviceInfoResult =
+            parseAndValidateDeviceInfo(deviceInfo.deviceInfo, provisionable, isFactory);
+    if (!deviceInfoResult) {
+        return deviceInfoResult.message();
+    }
+    std::unique_ptr<cppbor::Map> deviceInfoMap = deviceInfoResult.moveValue();
+    auto& signingKey = bccContents->back().pubKey;
+    auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
+                                          cppbor::Array()  // SignedMacAad
+                                                  .add(challenge)
+                                                  .add(std::move(deviceInfoMap))
+                                                  .add(keysToSignMac)
+                                                  .encode());
+    if (!macKey) {
+        return macKey.message();
+    }
+
+    auto coseMac0 = cppbor::Array()
+                            .add(cppbor::Map()  // protected
+                                         .add(ALGORITHM, HMAC_256)
+                                         .canonicalize()
+                                         .encode())
+                            .add(cppbor::Map())        // unprotected
+                            .add(keysToSign.encode())  // payload (keysToSign)
+                            .add(keysToSignMac);       // tag
+
+    auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
+    if (!macPayload) {
+        return macPayload.message();
+    }
+
+    return *bccContents;
+}
+
+ErrMsgOr<std::vector<BccEntryData>> verifyFactoryProtectedData(
+        const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
+        const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
+        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
+    return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
+                               eekId, supportedEekCurve, provisionable, challenge,
+                               /*isFactory=*/true);
+}
+
+ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData(
+        const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
+        const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
+        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
+        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
+    return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
+                               eekId, supportedEekCurve, provisionable, challenge,
+                               /*isFactory=*/false);
+}
+
+ErrMsgOr<X509_Ptr> parseX509Cert(const std::vector<uint8_t>& cert) {
+    CRYPTO_BUFFER_Ptr certBuf(CRYPTO_BUFFER_new(cert.data(), cert.size(), nullptr));
+    if (!certBuf.get()) {
+        return "Failed to create crypto buffer.";
+    }
+    X509_Ptr result(X509_parse_from_buffer(certBuf.get()));
+    if (!result.get()) {
+        return "Failed to parse certificate.";
+    }
+    return result;
+}
+
+std::string getX509IssuerName(const X509_Ptr& cert) {
+    char* name = X509_NAME_oneline(X509_get_issuer_name(cert.get()), nullptr, 0);
+    std::string result(name);
+    OPENSSL_free(name);
+    return result;
+}
+
+std::string getX509SubjectName(const X509_Ptr& cert) {
+    char* name = X509_NAME_oneline(X509_get_subject_name(cert.get()), nullptr, 0);
+    std::string result(name);
+    OPENSSL_free(name);
+    return result;
+}
+
+// Validates the certificate chain and returns the leaf public key.
+ErrMsgOr<bytevec> validateCertChain(const cppbor::Array& chain) {
+    uint8_t rawPubKey[64];
+    size_t rawPubKeySize = sizeof(rawPubKey);
+    for (size_t i = 0; i < chain.size(); ++i) {
+        // Root must be self-signed.
+        size_t signingCertIndex = (i > 1) ? i - 1 : i;
+        auto& keyCertItem = chain[i];
+        auto& signingCertItem = chain[signingCertIndex];
+        if (!keyCertItem || !keyCertItem->asBstr()) {
+            return "Key certificate must be a Bstr.";
+        }
+        if (!signingCertItem || !signingCertItem->asBstr()) {
+            return "Signing certificate must be a Bstr.";
+        }
+
+        auto keyCert = parseX509Cert(keyCertItem->asBstr()->value());
+        if (!keyCert) {
+            return keyCert.message();
+        }
+        auto signingCert = parseX509Cert(keyCertItem->asBstr()->value());
+        if (!signingCert) {
+            return signingCert.message();
+        }
+
+        EVP_PKEY_Ptr pubKey(X509_get_pubkey(keyCert->get()));
+        if (!pubKey.get()) {
+            return "Failed to get public key.";
+        }
+        EVP_PKEY_Ptr signingPubKey(X509_get_pubkey(signingCert->get()));
+        if (!signingPubKey.get()) {
+            return "Failed to get signing public key.";
+        }
+
+        if (!X509_verify(keyCert->get(), signingPubKey.get())) {
+            return "Verification of certificate " + std::to_string(i) +
+                   " faile. OpenSSL error string: " + ERR_error_string(ERR_get_error(), NULL);
+        }
+
+        auto certIssuer = getX509IssuerName(*keyCert);
+        auto signerSubj = getX509SubjectName(*signingCert);
+        if (certIssuer != signerSubj) {
+            return "Certificate " + std::to_string(i) + " has wrong issuer. Signer subject is " +
+                   signerSubj + " Issuer subject is " + certIssuer;
+        }
+
+        rawPubKeySize = sizeof(rawPubKey);
+        if (!EVP_PKEY_get_raw_public_key(pubKey.get(), rawPubKey, &rawPubKeySize)) {
+            return "Failed to get raw public key.";
+        }
+    }
+
+    return bytevec(rawPubKey, rawPubKey + rawPubKeySize);
+}
+
+std::string validateUdsCerts(const cppbor::Map& udsCerts, const bytevec& udsPub) {
+    for (const auto& [signerName, udsCertChain] : udsCerts) {
+        if (!signerName || !signerName->asTstr()) {
+            return "Signer Name must be a Tstr.";
+        }
+        if (!udsCertChain || !udsCertChain->asArray()) {
+            return "UDS certificate chain must be an Array.";
+        }
+        if (udsCertChain->asArray()->size() < 2) {
+            return "UDS certificate chain must have at least two entries: root and leaf.";
+        }
+
+        auto leafPubKey = validateCertChain(*udsCertChain->asArray());
+        if (!leafPubKey) {
+            return leafPubKey.message();
+        }
+        if (*leafPubKey != udsPub) {
+            return "Leaf public key in UDS certificat chain doesn't match UDS public key.";
+        }
+    }
+    return "";
+}
+
+ErrMsgOr<cppbor::Array> parseAndValidateCsrPayload(const cppbor::Array& keysToSign,
+                                                   const std::vector<uint8_t>& csrPayload,
+                                                   IRemotelyProvisionedComponent* provisionable,
+                                                   const std::vector<uint8_t>& challenge,
+                                                   bool isFactory) {
+    auto [parsedCsrPayload, _, errMsg] = cppbor::parse(csrPayload);
+    if (!parsedCsrPayload) {
+        return errMsg;
+    }
+    if (!parsedCsrPayload->asArray()) {
+        return "CSR payload is not a CBOR array.";
+    }
+    if (parsedCsrPayload->asArray()->size() != 5U) {
+        return "CSR payload must contain version, certificate type, device info, challenge, keys. "
+               "However, the parsed CSR payload has " +
+               std::to_string(parsedCsrPayload->asArray()->size()) + " entries.";
+    }
+
+    auto& signedVersion = parsedCsrPayload->asArray()->get(0);
+    auto& signedCertificateType = parsedCsrPayload->asArray()->get(1);
+    auto& signedDeviceInfo = parsedCsrPayload->asArray()->get(2);
+    auto& signedChallenge = parsedCsrPayload->asArray()->get(3);
+    auto& signedKeys = parsedCsrPayload->asArray()->get(4);
+
+    if (!signedVersion || !signedVersion->asUint() || signedVersion->asUint()->value() != 1U) {
+        return "CSR payload version must be an unsigned integer and must be equal to 1.";
+    }
+    if (!signedCertificateType || !signedCertificateType->asTstr()) {
+        // Certificate type is allowed to be extendend by vendor, i.e. we can't
+        // enforce its value.
+        return "Certificate type must be a Tstr.";
+    }
+    if (!signedDeviceInfo || !signedDeviceInfo->asMap()) {
+        return "Device info must be an Map.";
+    }
+    if (!signedChallenge || !signedChallenge->asBstr()) {
+        return "Challenge must be a Bstr.";
+    }
+    if (!signedKeys || !signedKeys->asArray()) {
+        return "Keys must be an Array.";
+    }
+
+    auto result = parseAndValidateDeviceInfo(signedDeviceInfo->asMap()->encode(), provisionable,
+                                             isFactory);
+    if (!result) {
+        return result.message();
+    }
+
+    if (challenge.size() < 32 || challenge.size() > 64) {
+        return "Challenge size must be between 32 and 64 bytes inclusive. "
+               "However, challenge is " +
+               std::to_string(challenge.size()) + " bytes long.";
+    }
+
+    auto challengeBstr = cppbor::Bstr(challenge);
+    if (*signedChallenge->asBstr() != challengeBstr) {
+        return "Signed challenge does not match."
+               "\n  Actual: " +
+               cppbor::prettyPrint(signedChallenge->asBstr(), 64 /* maxBStrSize */) +
+               "\nExpected: " + cppbor::prettyPrint(&challengeBstr, 64 /* maxBStrSize */);
+    }
+
+    if (signedKeys->asArray()->encode() != keysToSign.encode()) {
+        return "Signed keys do not match.";
+    }
+
+    return std::move(*parsedCsrPayload->asArray());
+}
+
+ErrMsgOr<std::vector<BccEntryData>> verifyCsr(const cppbor::Array& keysToSign,
+                                              const std::vector<uint8_t>& csr,
+                                              IRemotelyProvisionedComponent* provisionable,
+                                              const std::vector<uint8_t>& challenge,
+                                              bool isFactory) {
+    auto [parsedCsr, _, csrErrMsg] = cppbor::parse(csr);
+    if (!parsedCsr) {
+        return csrErrMsg;
+    }
+    if (!parsedCsr->asArray()) {
+        return "CSR is not a CBOR array.";
+    }
+    if (parsedCsr->asArray()->size() != 4U) {
+        return "CSR must contain version, UDS certificates, DICE chain, and signed data. "
+               "However, the parsed CSR has " +
+               std::to_string(parsedCsr->asArray()->size()) + " entries.";
+    }
+
+    auto& version = parsedCsr->asArray()->get(0);
+    auto& udsCerts = parsedCsr->asArray()->get(1);
+    auto& diceCertChain = parsedCsr->asArray()->get(2);
+    auto& signedData = parsedCsr->asArray()->get(3);
+
+    if (!version || !version->asUint() || version->asUint()->value() != 3U) {
+        return "Version must be an unsigned integer and must be equal to 3.";
+    }
+    if (!udsCerts || !udsCerts->asMap()) {
+        return "UdsCerts must be an Map.";
+    }
+    if (!diceCertChain || !diceCertChain->asArray()) {
+        return "DiceCertChain must be an Array.";
+    }
+    if (!signedData || !signedData->asArray()) {
+        return "SignedData must be an Array.";
+    }
+
+    RpcHardwareInfo info;
+    provisionable->getHardwareInfo(&info);
+    if (version->asUint()->value() != info.versionNumber) {
+        return "CSR version (" + std::to_string(version->asUint()->value()) +
+               ") does not match the remotely provisioned component version (" +
+               std::to_string(info.versionNumber) + ").";
+    }
+
+    // DICE chain is [ pubkey, + DiceChainEntry ]. Its format is the same as BCC from RKP v1-2.
+    auto diceContents = validateBcc(diceCertChain->asArray());
+    if (!diceContents) {
+        return diceContents.message() + "\n" + prettyPrint(diceCertChain.get());
+    }
+    if (diceContents->size() == 0U) {
+        return "The DICE chain is empty. It must contain at least one entry.";
+    }
+
+    auto& udsPub = diceContents->back().pubKey;
+
+    auto error = validateUdsCerts(*udsCerts->asMap(), udsPub);
+    if (!error.empty()) {
+        return error;
+    }
+
+    auto csrPayload = verifyAndParseCoseSign1(signedData->asArray(), udsPub, {} /* aad */);
+    if (!csrPayload) {
+        return csrPayload.message();
+    }
+
+    auto parsedCsrPayload = parseAndValidateCsrPayload(keysToSign, *csrPayload, provisionable,
+                                                       challenge, isFactory);
+    if (!parsedCsrPayload) {
+        return parsedCsrPayload.message();
+    }
+
+    return *diceContents;
+}
+
+ErrMsgOr<std::vector<BccEntryData>> verifyFactoryCsr(const cppbor::Array& keysToSign,
+                                                     const std::vector<uint8_t>& csr,
+                                                     IRemotelyProvisionedComponent* provisionable,
+                                                     const std::vector<uint8_t>& challenge) {
+    return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/true);
+}
+
+ErrMsgOr<std::vector<BccEntryData>> verifyProductionCsr(
+        const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
+        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
+    return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/false);
+}
+
 }  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/secureclock/aidl/Android.bp b/security/secureclock/aidl/Android.bp
index 00a6ba3..853ad89 100644
--- a/security/secureclock/aidl/Android.bp
+++ b/security/secureclock/aidl/Android.bp
@@ -18,11 +18,6 @@
         java: {
             platform_apis: true,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
         rust: {
             enabled: true,
             apex_available: [
diff --git a/security/sharedsecret/aidl/Android.bp b/security/sharedsecret/aidl/Android.bp
index f1fce74..fe77c10 100644
--- a/security/sharedsecret/aidl/Android.bp
+++ b/security/sharedsecret/aidl/Android.bp
@@ -18,11 +18,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
         rust: {
             enabled: true,
         },
diff --git a/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl b/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
index 8144699..b72f0de 100644
--- a/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
+++ b/security/sharedsecret/aidl/android/hardware/security/sharedsecret/SharedSecretParameters.aidl
@@ -33,9 +33,9 @@
     byte[] seed;
 
     /**
-     * A 32-byte value which is guaranteed to be different each time
-     * getSharedSecretParameters() is called.  Probabilistic uniqueness (i.e. random) is acceptable,
-     * though a stronger uniqueness guarantee (e.g. counter) is recommended where possible.
+     * A 32-byte value which is guaranteed to be different each time getSharedSecretParameters() is
+     * called after a restart.  Probabilistic uniqueness (i.e. random) is acceptable, though a
+     * stronger uniqueness guarantee (e.g. counter) is recommended where possible.
      */
     byte[] nonce;
 }
diff --git a/sensors/2.0/multihal/android.hardware.sensors@2.0-service-multihal.rc b/sensors/2.0/multihal/android.hardware.sensors@2.0-service-multihal.rc
index 8867a1a..c874604 100644
--- a/sensors/2.0/multihal/android.hardware.sensors@2.0-service-multihal.rc
+++ b/sensors/2.0/multihal/android.hardware.sensors@2.0-service-multihal.rc
@@ -1,7 +1,7 @@
 service vendor.sensors-hal-2-0-multihal /vendor/bin/hw/android.hardware.sensors@2.0-service.multihal
     class hal
     user system
-    group system wakelock context_hub
+    group system wakelock context_hub input
     task_profiles ServiceCapacityLow
     capabilities BLOCK_SUSPEND
     rlimit rtprio 10 10
diff --git a/sensors/2.1/multihal/android.hardware.sensors@2.1-service-multihal.rc b/sensors/2.1/multihal/android.hardware.sensors@2.1-service-multihal.rc
index f47e060..deea16e 100644
--- a/sensors/2.1/multihal/android.hardware.sensors@2.1-service-multihal.rc
+++ b/sensors/2.1/multihal/android.hardware.sensors@2.1-service-multihal.rc
@@ -1,7 +1,7 @@
 service vendor.sensors-hal-2-1-multihal /vendor/bin/hw/android.hardware.sensors@2.1-service.multihal
     class hal
     user system
-    group system wakelock context_hub
+    group system wakelock context_hub input
     task_profiles ServiceCapacityLow
     capabilities BLOCK_SUSPEND
     rlimit rtprio 10 10
diff --git a/sensors/aidl/Android.bp b/sensors/aidl/Android.bp
index 1c2d83f..d04017c 100644
--- a/sensors/aidl/Android.bp
+++ b/sensors/aidl/Android.bp
@@ -23,11 +23,6 @@
         java: {
             enabled: false,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
index f3cbd78..f2c92ae 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
@@ -351,11 +351,11 @@
                   minDelayAverageInterval / 10);
 
         // fastest rate sampling time is close to spec
-        EXPECT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
+        EXPECT_LE(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
                   minSamplingPeriodInNs / 10);
 
         // slowest rate sampling time is close to spec
-        EXPECT_LT(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs),
+        EXPECT_LE(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs),
                   maxSamplingPeriodInNs / 10);
     }
 
diff --git a/soundtrigger/2.3/cli/Android.bp b/soundtrigger/2.3/cli/Android.bp
index 27d7b30..883bf2b 100644
--- a/soundtrigger/2.3/cli/Android.bp
+++ b/soundtrigger/2.3/cli/Android.bp
@@ -9,7 +9,7 @@
 
 java_binary {
     name: "sthal_cli_2.3",
-    wrapper: "sthal_cli_2.3",
+    wrapper: "sthal_cli_2.3.sh",
     srcs: ["java/**/*.java"],
     static_libs: [
         "android.hardware.soundtrigger-V2.3-java",
diff --git a/soundtrigger/2.3/cli/sthal_cli_2.3 b/soundtrigger/2.3/cli/sthal_cli_2.3.sh
similarity index 100%
rename from soundtrigger/2.3/cli/sthal_cli_2.3
rename to soundtrigger/2.3/cli/sthal_cli_2.3.sh
diff --git a/soundtrigger/aidl/Android.bp b/soundtrigger/aidl/Android.bp
index 448895c..27d43d3 100644
--- a/soundtrigger/aidl/Android.bp
+++ b/soundtrigger/aidl/Android.bp
@@ -33,17 +33,26 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
             version: "1",
             imports: ["android.media.soundtrigger.types-V1"],
         },
+        // IMPORTANT: Update latest_android_hardware_soundtrigger3 every time
+        // you add the latest frozen version to versions_with_info
     ],
+}
 
+// Note: This should always be one version ahead of the last frozen version
+latest_android_hardware_soundtrigger3 = "android.hardware.soundtrigger3-V1"
+
+// Modules that depend on android.hardware.soundtrigger3 directly can include
+// the following java_defaults to avoid explicitly managing dependency versions
+// across many scattered files.
+java_defaults {
+    name: "latest_android_hardware_soundtrigger3_java_static",
+    static_libs: [
+        latest_android_hardware_soundtrigger3 + "-java",
+    ],
 }
diff --git a/soundtrigger/aidl/cli/Android.bp b/soundtrigger/aidl/cli/Android.bp
index e8999ff..935e438 100644
--- a/soundtrigger/aidl/cli/Android.bp
+++ b/soundtrigger/aidl/cli/Android.bp
@@ -9,7 +9,7 @@
 
 java_binary {
     name: "sthal_cli_3",
-    wrapper: "sthal_cli_3",
+    wrapper: "sthal_cli_3.sh",
     srcs: ["java/**/*.java"],
     static_libs: [
         "android.hardware.soundtrigger3-V1-java",
diff --git a/soundtrigger/aidl/cli/sthal_cli_3 b/soundtrigger/aidl/cli/sthal_cli_3.sh
similarity index 100%
rename from soundtrigger/aidl/cli/sthal_cli_3
rename to soundtrigger/aidl/cli/sthal_cli_3.sh
diff --git a/tests/extension/vibrator/aidl/default/CustomVibrator.cpp b/tests/extension/vibrator/aidl/default/CustomVibrator.cpp
index 2f3dfcb..7a7c58b 100644
--- a/tests/extension/vibrator/aidl/default/CustomVibrator.cpp
+++ b/tests/extension/vibrator/aidl/default/CustomVibrator.cpp
@@ -57,4 +57,12 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::SpAIBinder CustomVibrator::createBinder() {
+    auto binder = BnCustomVibrator::createBinder();
+    // e.g. AIBinder_setInheritRt(binder.get(), true);
+    // e.g. AIBinder_setMinSchedulerPolicy(binder.get(), SCHED_NORMAL, 20);
+    // e.g. AIBinder_setRequestingSid(binder.get(), true);
+    return binder;
+}
+
 }  // namespace aidl::android::hardware::tests::extension::vibrator
diff --git a/tests/extension/vibrator/aidl/default/CustomVibrator.h b/tests/extension/vibrator/aidl/default/CustomVibrator.h
index 6dc5743..084a557 100644
--- a/tests/extension/vibrator/aidl/default/CustomVibrator.h
+++ b/tests/extension/vibrator/aidl/default/CustomVibrator.h
@@ -29,6 +29,12 @@
     ndk::ScopedAStatus perform(VendorEffect effect,
                                const std::shared_ptr<IVibratorCallback>& callback,
                                int32_t* _aidl_return) override;
+
+  private:
+    // override for AIBinder_setInheritRt, AIBinder_setMinSchedulerPolicy, or
+    // AIBinder_setRequestingSid calling this in the constructor or elsewhere, the binder would
+    // immediately be destroyed.
+    ndk::SpAIBinder createBinder() override;
 };
 
 }  // namespace aidl::android::hardware::tests::extension::vibrator
diff --git a/thermal/OWNERS b/thermal/OWNERS
new file mode 100644
index 0000000..7229b22
--- /dev/null
+++ b/thermal/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 826709
+
+# ADPF virtual team
+lpy@google.com
+wvw@google.com
diff --git a/thermal/aidl/Android.bp b/thermal/aidl/Android.bp
new file mode 100644
index 0000000..b132746
--- /dev/null
+++ b/thermal/aidl/Android.bp
@@ -0,0 +1,39 @@
+// 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.thermal",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/thermal/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: true,
+        },
+        java: {
+            platform_apis: true,
+        },
+    },
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl
new file mode 100644
index 0000000..50be508
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl
@@ -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
+ *
+1 *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.thermal;
+@VintfStability
+parcelable CoolingDevice {
+  android.hardware.thermal.CoolingType type;
+  String name;
+  long value;
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingType.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingType.aidl
new file mode 100644
index 0000000..57c8939
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingType.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.thermal;
+@Backing(type="int") @VintfStability
+enum CoolingType {
+  FAN = 0,
+  BATTERY = 1,
+  CPU = 2,
+  GPU = 3,
+  MODEM = 4,
+  NPU = 5,
+  COMPONENT = 6,
+  TPU = 7,
+  POWER_AMPLIFIER = 8,
+  DISPLAY = 9,
+  SPEAKER = 10,
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
new file mode 100644
index 0000000..0aed5ec
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.thermal;
+@VintfStability
+interface IThermal {
+  android.hardware.thermal.CoolingDevice[] getCoolingDevices();
+  android.hardware.thermal.CoolingDevice[] getCoolingDevicesWithType(in android.hardware.thermal.CoolingType type);
+  android.hardware.thermal.Temperature[] getTemperatures();
+  android.hardware.thermal.Temperature[] getTemperaturesWithType(in android.hardware.thermal.TemperatureType type);
+  android.hardware.thermal.TemperatureThreshold[] getTemperatureThresholds();
+  android.hardware.thermal.TemperatureThreshold[] getTemperatureThresholdsWithType(in android.hardware.thermal.TemperatureType type);
+  void registerThermalChangedCallback(in android.hardware.thermal.IThermalChangedCallback callback);
+  void registerThermalChangedCallbackWithType(in android.hardware.thermal.IThermalChangedCallback callback, in android.hardware.thermal.TemperatureType type);
+  void unregisterThermalChangedCallback(in android.hardware.thermal.IThermalChangedCallback callback);
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl
new file mode 100644
index 0000000..6b3f922
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.thermal;
+@VintfStability
+interface IThermalChangedCallback {
+  oneway void notifyThrottling(in android.hardware.thermal.Temperature temperature);
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/Temperature.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/Temperature.aidl
new file mode 100644
index 0000000..7156415
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/Temperature.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.thermal;
+@VintfStability
+parcelable Temperature {
+  android.hardware.thermal.TemperatureType type;
+  String name;
+  float value;
+  android.hardware.thermal.ThrottlingSeverity throttlingStatus;
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureThreshold.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureThreshold.aidl
new file mode 100644
index 0000000..6da561f
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureThreshold.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.thermal;
+@VintfStability
+parcelable TemperatureThreshold {
+  android.hardware.thermal.TemperatureType type;
+  String name;
+  float[] hotThrottlingThresholds;
+  float[] coldThrottlingThresholds;
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureType.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureType.aidl
new file mode 100644
index 0000000..c6a08c1
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureType.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.thermal;
+@Backing(type="int") @VintfStability
+enum TemperatureType {
+  UNKNOWN = -1,
+  CPU = 0,
+  GPU = 1,
+  BATTERY = 2,
+  SKIN = 3,
+  USB_PORT = 4,
+  POWER_AMPLIFIER = 5,
+  BCL_VOLTAGE = 6,
+  BCL_CURRENT = 7,
+  BCL_PERCENTAGE = 8,
+  NPU = 9,
+  TPU = 10,
+  DISPLAY = 11,
+  MODEM = 12,
+  SOC = 13,
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ThrottlingSeverity.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ThrottlingSeverity.aidl
new file mode 100644
index 0000000..e86b581
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ThrottlingSeverity.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.thermal;
+@Backing(type="int") @VintfStability
+enum ThrottlingSeverity {
+  NONE = 0,
+  LIGHT = 1,
+  MODERATE = 2,
+  SEVERE = 3,
+  CRITICAL = 4,
+  EMERGENCY = 5,
+  SHUTDOWN = 6,
+}
diff --git a/thermal/aidl/android/hardware/thermal/CoolingDevice.aidl b/thermal/aidl/android/hardware/thermal/CoolingDevice.aidl
new file mode 100644
index 0000000..6d974a5
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/CoolingDevice.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
+ *
+1 *      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.thermal;
+
+import android.hardware.thermal.CoolingType;
+
+@VintfStability
+parcelable CoolingDevice {
+    /**
+     * This cooling device type, CPU, GPU, BATTERY, and etc.
+     */
+    CoolingType type;
+    /**
+     * Name of this cooling device.
+     * All cooling devices of the same "type" must have a different "name".
+     * The name is usually defined in kernel device tree, and this is for client
+     * logging purpose.
+     */
+    String name;
+    /**
+     * Current throttle state of the cooling device. The value can any unsigned integer
+     * numbers between 0 and max_state defined in its driver, usually representing the
+     * associated device's power state. 0 means device is not in throttling, higher value
+     * means deeper throttling.
+     */
+    long value;
+}
diff --git a/thermal/aidl/android/hardware/thermal/CoolingType.aidl b/thermal/aidl/android/hardware/thermal/CoolingType.aidl
new file mode 100644
index 0000000..1b430d2
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/CoolingType.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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.thermal;
+
+/**
+ * Device cooling device types
+ */
+@VintfStability
+@Backing(type="int")
+enum CoolingType {
+    FAN,
+    BATTERY,
+    CPU,
+    GPU,
+    MODEM,
+    NPU,
+    COMPONENT,
+    TPU,
+    POWER_AMPLIFIER,
+    DISPLAY,
+    SPEAKER,
+}
diff --git a/thermal/aidl/android/hardware/thermal/IThermal.aidl b/thermal/aidl/android/hardware/thermal/IThermal.aidl
new file mode 100644
index 0000000..8b79cb4
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/IThermal.aidl
@@ -0,0 +1,202 @@
+/*
+ * 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.thermal;
+
+import android.hardware.thermal.CoolingDevice;
+import android.hardware.thermal.CoolingType;
+import android.hardware.thermal.IThermalChangedCallback;
+import android.hardware.thermal.Temperature;
+import android.hardware.thermal.TemperatureThreshold;
+import android.hardware.thermal.TemperatureType;
+
+@VintfStability
+interface IThermal {
+    /**
+     * Retrieves the cooling devices information.
+     *
+     * @return devices If succeed, it's filled with the
+     *    current cooling device information. The order of built-in cooling
+     *    devices in the list must be kept the same regardless the number
+     *    of calls to this method even if they go offline, if these devices
+     *    exist on boot. The method always returns and never removes from
+     *    the list such cooling devices.
+     *
+     * @throws ScopedAStatus Status of the operation. If status code is not
+     *    STATUS_OK, getMessage() must be populated with the human-readable
+     *    error message.
+     */
+    CoolingDevice[] getCoolingDevices();
+
+    /**
+     * Retrieves the cooling devices information of a given CoolingType.
+     *
+     * @param type the CoolingDevice such as CPU/GPU.
+     *
+     * @return devices If succeed, it's filled with the current
+     *    cooling device information. The order of built-in cooling
+     *    devices in the list must be kept the same regardless of the number
+     *    of calls to this method even if they go offline, if these devices
+     *    exist on boot. The method always returns and never removes from
+     *    the list such cooling devices.
+     *
+     * @throws ScopedAStatus Status of the operation. If status code is not
+     *    STATUS_OK, the getMessage() must be populated with the human-readable
+     *    error message.
+     */
+    CoolingDevice[] getCoolingDevicesWithType(in CoolingType type);
+
+    /**
+     * Retrieves temperatures in Celsius.
+     *
+     * @return temperatures If succeed, it's filled with the
+     *    current temperatures. The order of temperatures of built-in
+     *    devices (such as CPUs, GPUs and etc.) in the list must be kept
+     *    the same regardless the number of calls to this method even if
+     *    they go offline, if these devices exist on boot. The method
+     *    always returns and never removes such temperatures.
+     *
+     * @throws ScopedAStatus Status of the operation. If status code is not
+     *    STATUS_OK, the getMessage() must be populated with the human-readable
+     *    error message.
+     */
+    Temperature[] getTemperatures();
+
+    /**
+     * Retrieves temperatures in Celsius with a given TemperatureType.
+     *
+     * @param type the TemperatureType such as battery or skin.
+     *
+     * @return temperatures If succeed, it's filled with the
+     *    current temperatures. The order of temperatures of built-in
+     *    devices (such as CPUs, GPUs and etc.) in the list must be kept
+     *    the same regardless of the number of calls to this method even if
+     *    they go offline, if these devices exist on boot. The method
+     *    always returns and never removes such temperatures.
+     *
+     * @throws ScopedAStatus Status of the operation. If status code is not
+     *    STATUS_OK, the getMessage() must be populated with the human-readable
+     *    error message.
+     */
+    Temperature[] getTemperaturesWithType(in TemperatureType type);
+
+    /**
+     * Retrieves static temperature thresholds in Celsius.
+     *
+     * @return temperatureThresholds If succeed, it's filled with the
+     *    temperatures thresholds. The order of temperatures of built-in
+     *    devices (such as CPUs, GPUs and etc.) in the list must be kept
+     *    the same regardless of the number of calls to this method even if
+     *    they go offline, if these devices exist on boot. The method
+     *    always returns and never removes such temperatures. The thresholds
+     *    are returned as static values and must not change across calls. The actual
+     *    throttling state is determined in device thermal mitigation policy/agorithm
+     *    which might not be simple thresholds so these values Thermal HAL provided
+     *    may not be accurate to detemin the throttling status. To get accurate
+     *    throttling status, use getTemperatures or registerThermalChangedCallback
+     *    and listen to the callback.
+     *
+     * @throws ScopedAStatus Status of the operation. If status code is not
+     *    STATUS_OK, the getMessage() must be populated with the human-readable
+     *    error message.
+     */
+    TemperatureThreshold[] getTemperatureThresholds();
+
+    /**
+     * Retrieves static temperature thresholds in Celsius of a given temperature
+     * type.
+     *
+     * @param type the TemperatureType such as battery or skin.
+     *
+     * @return temperatureThresholds If succeed, it's filled with the
+     *    temperatures thresholds. The order of temperatures of built-in
+     *    devices (such as CPUs, GPUs and etc.) in the list must be kept
+     *    the same regardless of the number of calls to this method even if
+     *    they go offline, if these devices exist on boot. The method
+     *    always returns and never removes such temperatures. The thresholds
+     *    are returned as static values and must not change across calls. The actual
+     *    throttling state is determined in device thermal mitigation policy/agorithm
+     *    which might not be simple thresholds so these values Thermal HAL provided
+     *    may not be accurate to detemin the throttling status. To get accurate
+     *    throttling status, use getTemperatures or registerThermalChangedCallback
+     *    and listen to the callback.
+     *
+     * @throws ScopedAStatus Status of the operation. If status code is not
+     *    STATUS_OK, the getMessage() must be populated with the human-readable
+     *    error message.
+     */
+    TemperatureThreshold[] getTemperatureThresholdsWithType(in TemperatureType type);
+
+    /**
+     * Register an IThermalChangedCallback, used by the Thermal HAL to receive
+     * thermal events when thermal mitigation status changed.
+     * Multiple registrations with different IThermalChangedCallback must be allowed.
+     * Multiple registrations with same IThermalChangedCallback is not allowed, client
+     * should unregister the given IThermalChangedCallback first.
+     *
+     * @param callback the IThermalChangedCallback to use for receiving
+     *    thermal events. if nullptr callback is given, the status code will be
+     *    STATUS_BAD_VALUE and the operation will fail.
+     *
+     * @throws ScopedAStatus Status of the operation. If status code is not
+     *    STATUS_OK, the getMessage() must be populated with the human-readable
+     *    error message. If callback is given nullptr, the returned status code
+     *    will be STATUS_BAD_VALUE and the exception will be EX_ILLEGAL_ARGUMENT.
+     *    if callback is already registered, the returned status code will be
+     *    STATUS_INVALID_OPERATION, the exception will be EX_ILLEGAL_ARGUMENT.
+     */
+    void registerThermalChangedCallback(in IThermalChangedCallback callback);
+
+    /**
+     * Register an IThermalChangedCallback for a given TemperatureType, used by
+     * the Thermal HAL to receive thermal events when thermal mitigation status
+     * changed.
+     * Multiple registrations with different IThermalChangedCallback must be allowed.
+     * Multiple registrations with same IThermalChangedCallback is not allowed, client
+     * should unregister the given IThermalChangedCallback first.
+     *
+     * @param callback the IThermalChangedCallback to use for receiving
+     *    thermal events. if nullptr callback is given, the status code will be
+     *    STATUS_BAD_VALUE and the operation will fail.
+     * @param type the type to be filtered.
+     *
+     * @throws ScopedAStatus Status of the operation. If status code is not
+     *    STATUS_OK, the getMessage() must be populated with the human-readable
+     *    error message. If callback is given nullptr, the returned status code
+     *    will be STATUS_BAD_VALUE and the exception will be EX_ILLEGAL_ARGUMENT.
+     *    if callback is already registered, the returned status code will be
+     *    STATUS_INVALID_OPERATION, the exception will be EX_ILLEGAL_ARGUMENT.
+     */
+    void registerThermalChangedCallbackWithType(
+            in IThermalChangedCallback callback, in TemperatureType type);
+
+    /**
+     * Unregister an IThermalChangedCallback, used by the Thermal HAL
+     * to receive thermal events when thermal mitigation status changed.
+     *
+     * @param callback the IThermalChangedCallback to use for receiving
+     *    thermal events. if nullptr callback is given, the status code will be
+     *    STATUS_BAD_VALUE and the operation will fail.
+     *
+     * @throws ScopedAStatus Status of the operation. If status code is not
+     *    STATUS_OK, the getMessage() must be populated with the human-readable
+     *    error message. If callback is given nullptr, the returned status code
+     *    will be STATUS_BAD_VALUE and the exception will be EX_ILLEGAL_ARGUMENT.
+     *    if callback is not registered, the returned status code will be
+     *    STATUS_INVALID_OPERATION, the exception will be EX_ILLEGAL_ARGUMENT.
+     */
+    void unregisterThermalChangedCallback(in IThermalChangedCallback callback);
+}
diff --git a/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl b/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl
new file mode 100644
index 0000000..6fe2dac
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.thermal;
+
+import android.hardware.thermal.Temperature;
+
+/**
+ * IThermalChangedCallback send throttling notification to clients.
+ */
+@VintfStability
+interface IThermalChangedCallback {
+    /**
+     * Send a thermal throttling event to all ThermalHAL
+     * thermal event listeners.
+     *
+     * @param temperature The temperature associated with the
+     *    throttling event.
+     */
+    oneway void notifyThrottling(in Temperature temperature);
+}
diff --git a/thermal/aidl/android/hardware/thermal/Temperature.aidl b/thermal/aidl/android/hardware/thermal/Temperature.aidl
new file mode 100644
index 0000000..f0041ed
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/Temperature.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.thermal;
+
+import android.hardware.thermal.TemperatureType;
+import android.hardware.thermal.ThrottlingSeverity;
+
+@VintfStability
+parcelable Temperature {
+    /**
+     * This temperature's type.
+     */
+    TemperatureType type;
+    /**
+     * Name of this temperature matching the TemperatureThreshold.
+     * All temperatures of the same "type" must have a different "name",
+     * e.g., cpu0, battery. Clients use it to match with TemperatureThreshold
+     * struct.
+     */
+    String name;
+    /**
+     * For BCL, this is the current reading of the virtual sensor and the unit is
+     * millivolt, milliamp, percentage for BCL_VOLTAGE, BCL_CURRENT and BCL_PERCENTAGE
+     * respectively. For everything else, this is the current temperature in Celsius.
+     * If not available set by HAL to NAN.
+     */
+    float value;
+    /**
+     * The current throttling level of the sensor.
+     */
+    ThrottlingSeverity throttlingStatus;
+}
diff --git a/thermal/aidl/android/hardware/thermal/TemperatureThreshold.aidl b/thermal/aidl/android/hardware/thermal/TemperatureThreshold.aidl
new file mode 100644
index 0000000..9ecdab3
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/TemperatureThreshold.aidl
@@ -0,0 +1,49 @@
+/*
+ * 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.thermal;
+
+import android.hardware.thermal.TemperatureType;
+
+@VintfStability
+parcelable TemperatureThreshold {
+    /**
+     * This temperature's type.
+     */
+    TemperatureType type;
+    /**
+     * Name of this temperature matching the Temperature struct.
+     * All temperatures of the same "type" must have a different "name",
+     * e.g., cpu0, battery. Clients use it to match Temperature struct.
+     */
+    String name;
+    /**
+     * Hot throttling temperature constant for this temperature sensor in
+     * level defined in ThrottlingSeverity including shutdown. Throttling
+     * happens when temperature >= threshold. If not available, set to NAN.
+     * Unit is same as Temperature's value.
+     * The number of thresholds must be the same as ThrottlingSeverity#len.
+     */
+    float[] hotThrottlingThresholds;
+    /**
+     * Cold throttling temperature constant for this temperature sensor in
+     * level defined in ThrottlingSeverity including shutdown. Throttling
+     * happens when temperature <= threshold. If not available, set to NAN.
+     * Unit is same as Temperature's value.
+     * The number of theresholds must be the same as ThrottlingSeverity#len.
+     */
+    float[] coldThrottlingThresholds;
+}
diff --git a/thermal/aidl/android/hardware/thermal/TemperatureType.aidl b/thermal/aidl/android/hardware/thermal/TemperatureType.aidl
new file mode 100644
index 0000000..aebe7ce
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/TemperatureType.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.thermal;
+
+/**
+ * Device temperature types
+ */
+@VintfStability
+@Backing(type="int")
+enum TemperatureType {
+    UNKNOWN = -1,
+    CPU = 0,
+    GPU = 1,
+    BATTERY = 2,
+    SKIN = 3,
+    USB_PORT = 4,
+    POWER_AMPLIFIER = 5,
+    /**
+     * Battery Current Limit - virtual sensors
+     */
+    BCL_VOLTAGE = 6,
+    BCL_CURRENT = 7,
+    BCL_PERCENTAGE = 8,
+    /**
+     * Neural Processing Unit
+     */
+    NPU = 9,
+    TPU = 10,
+    DISPLAY = 11,
+    MODEM = 12,
+    SOC = 13,
+}
diff --git a/thermal/aidl/android/hardware/thermal/ThrottlingSeverity.aidl b/thermal/aidl/android/hardware/thermal/ThrottlingSeverity.aidl
new file mode 100644
index 0000000..29f0724
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/ThrottlingSeverity.aidl
@@ -0,0 +1,55 @@
+/*
+ * 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.thermal;
+
+/**
+ * Device throttling severity
+ */
+@VintfStability
+@Backing(type="int")
+enum ThrottlingSeverity {
+    /**
+     * Not under throttling.
+     */
+    NONE = 0,
+    /**
+     * Light throttling where UX is not impacted.
+     */
+    LIGHT,
+    /**
+     * Moderate throttling where UX is not largely impacted.
+     */
+    MODERATE,
+    /**
+     * Severe throttling where UX is largely impacted.
+     * Similar to 1.0 throttlingThreshold.
+     */
+    SEVERE,
+    /**
+     * Platform has done everything to reduce power.
+     */
+    CRITICAL,
+    /**
+     * Key components in platform are shutting down due to thermal condition.
+     * Device functionalities will be limited.
+     */
+    EMERGENCY,
+    /**
+     * Need shutdown immediately.
+     */
+    SHUTDOWN,
+}
diff --git a/thermal/aidl/default/Android.bp b/thermal/aidl/default/Android.bp
new file mode 100644
index 0000000..49a578b
--- /dev/null
+++ b/thermal/aidl/default/Android.bp
@@ -0,0 +1,49 @@
+// 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.thermal-service.example",
+    relative_install_path: "hw",
+    init_rc: [":android.hardware.thermal.example.rc"],
+    vintf_fragments: [":android.hardware.thermal.example.xml"],
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "android.hardware.thermal-V1-ndk",
+    ],
+    srcs: [
+        "main.cpp",
+        "Thermal.cpp",
+    ],
+}
+
+filegroup {
+    name: "android.hardware.thermal.example.xml",
+    srcs: ["thermal-example.xml"],
+}
+
+filegroup {
+    name: "android.hardware.thermal.example.rc",
+    srcs: ["thermal-example.rc"],
+}
diff --git a/thermal/aidl/default/Thermal.cpp b/thermal/aidl/default/Thermal.cpp
new file mode 100644
index 0000000..5771e0e
--- /dev/null
+++ b/thermal/aidl/default/Thermal.cpp
@@ -0,0 +1,101 @@
+/*
+ * 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 "Thermal.h"
+
+#include <android-base/logging.h>
+
+namespace aidl::android::hardware::thermal::impl::example {
+
+using ndk::ScopedAStatus;
+
+ScopedAStatus Thermal::getCoolingDevices(std::vector<CoolingDevice>* /* out_devices */) {
+    LOG(VERBOSE) << __func__;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getCoolingDevicesWithType(CoolingType in_type,
+                                                 std::vector<CoolingDevice>* /* out_devices */) {
+    LOG(VERBOSE) << __func__ << " CoolingType: " << static_cast<int32_t>(in_type);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getTemperatures(std::vector<Temperature>* /* out_temperatures */) {
+    LOG(VERBOSE) << __func__;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getTemperaturesWithType(TemperatureType in_type,
+                                               std::vector<Temperature>* /* out_temperatures */) {
+    LOG(VERBOSE) << __func__ << " TemperatureType: " << static_cast<int32_t>(in_type);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getTemperatureThresholds(
+        std::vector<TemperatureThreshold>* /* out_temperatureThresholds */) {
+    LOG(VERBOSE) << __func__;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getTemperatureThresholdsWithType(
+        TemperatureType in_type,
+        std::vector<TemperatureThreshold>* /* out_temperatureThresholds */) {
+    LOG(VERBOSE) << __func__ << " TemperatureType: " << static_cast<int32_t>(in_type);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::registerThermalChangedCallback(
+        const std::shared_ptr<IThermalChangedCallback>& in_callback) {
+    LOG(VERBOSE) << __func__ << " IThermalChangedCallback: " << in_callback;
+    if (in_callback == nullptr) {
+        return ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
+    }
+    if (mCallbacks.find(in_callback) != mCallbacks.end()) {
+        return ScopedAStatus::fromStatus(STATUS_INVALID_OPERATION);
+    }
+    mCallbacks.insert(in_callback);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::registerThermalChangedCallbackWithType(
+        const std::shared_ptr<IThermalChangedCallback>& in_callback, TemperatureType in_type) {
+    LOG(VERBOSE) << __func__ << " IThermalChangedCallback: " << in_callback
+                 << ", TemperatureType: " << static_cast<int32_t>(in_type);
+    if (in_callback == nullptr) {
+        return ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
+    }
+    if (mCallbacks.find(in_callback) != mCallbacks.end()) {
+        return ScopedAStatus::fromStatus(STATUS_INVALID_OPERATION);
+    }
+    mCallbacks.insert(in_callback);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::unregisterThermalChangedCallback(
+        const std::shared_ptr<IThermalChangedCallback>& in_callback) {
+    LOG(VERBOSE) << __func__ << " IThermalChangedCallback: " << in_callback;
+    bool found = false;
+    if (in_callback == nullptr) {
+        return ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
+    }
+    if (mCallbacks.find(in_callback) == mCallbacks.end()) {
+        return ScopedAStatus::fromStatus(STATUS_INVALID_OPERATION);
+    }
+    mCallbacks.erase(in_callback);
+    return ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::thermal::impl::example
diff --git a/thermal/aidl/default/Thermal.h b/thermal/aidl/default/Thermal.h
new file mode 100644
index 0000000..788af4a
--- /dev/null
+++ b/thermal/aidl/default/Thermal.h
@@ -0,0 +1,65 @@
+/*
+ * 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 <set>
+
+#include <aidl/android/hardware/thermal/BnThermal.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace impl {
+namespace example {
+
+class Thermal : public BnThermal {
+  public:
+    ndk::ScopedAStatus getCoolingDevices(std::vector<CoolingDevice>* out_devices) override;
+    ndk::ScopedAStatus getCoolingDevicesWithType(CoolingType in_type,
+                                                 std::vector<CoolingDevice>* out_devices) override;
+
+    ndk::ScopedAStatus getTemperatures(std::vector<Temperature>* out_temperatures) override;
+    ndk::ScopedAStatus getTemperaturesWithType(TemperatureType in_type,
+                                               std::vector<Temperature>* out_temperatures) override;
+
+    ndk::ScopedAStatus getTemperatureThresholds(
+            std::vector<TemperatureThreshold>* out_temperatureThresholds) override;
+
+    ndk::ScopedAStatus getTemperatureThresholdsWithType(
+            TemperatureType in_type,
+            std::vector<TemperatureThreshold>* out_temperatureThresholds) override;
+
+    ndk::ScopedAStatus registerThermalChangedCallback(
+            const std::shared_ptr<IThermalChangedCallback>& in_callback) override;
+    ndk::ScopedAStatus registerThermalChangedCallbackWithType(
+            const std::shared_ptr<IThermalChangedCallback>& in_callback,
+            TemperatureType in_type) override;
+
+    ndk::ScopedAStatus unregisterThermalChangedCallback(
+            const std::shared_ptr<IThermalChangedCallback>& in_callback) override;
+
+  private:
+    std::set<std::shared_ptr<IThermalChangedCallback>> mCallbacks;
+};
+
+}  // namespace example
+}  // namespace impl
+}  // namespace thermal
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/thermal/aidl/default/main.cpp b/thermal/aidl/default/main.cpp
new file mode 100644
index 0000000..61d8ad0
--- /dev/null
+++ b/thermal/aidl/default/main.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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 "Thermal.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::thermal::impl::example::Thermal;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    std::shared_ptr<Thermal> thermal = ndk::SharedRefBase::make<Thermal>();
+
+    const std::string instance = std::string() + Thermal::descriptor + "/default";
+    binder_status_t status =
+            AServiceManager_addService(thermal->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reach
+}
diff --git a/thermal/aidl/default/thermal-example.rc b/thermal/aidl/default/thermal-example.rc
new file mode 100644
index 0000000..591ca03
--- /dev/null
+++ b/thermal/aidl/default/thermal-example.rc
@@ -0,0 +1,4 @@
+service vendor.thermal-example /vendor/bin/hw/android.hardware.thermal-service.example
+    class hal
+    user nobody
+    group system
diff --git a/thermal/aidl/default/thermal-example.xml b/thermal/aidl/default/thermal-example.xml
new file mode 100644
index 0000000..bdee744
--- /dev/null
+++ b/thermal/aidl/default/thermal-example.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.thermal</name>
+        <version>1</version>
+        <fqname>IThermal/default</fqname>
+    </hal>
+</manifest>
diff --git a/thermal/aidl/vts/Android.bp b/thermal/aidl/vts/Android.bp
new file mode 100644
index 0000000..b00eb33
--- /dev/null
+++ b/thermal/aidl/vts/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"],
+}
+
+cc_test {
+    name: "VtsHalThermalTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalThermalTargetTest.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.thermal-V1-ndk",
+    ],
+    test_suites: [
+        "vts",
+    ],
+}
diff --git a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
new file mode 100644
index 0000000..b93250e
--- /dev/null
+++ b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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 <algorithm>
+#include <chrono>
+#include <cmath>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+#define LOG_TAG "thermal_aidl_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/thermal/BnThermal.h>
+#include <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_status.h>
+#include <gtest/gtest.h>
+
+#include <unistd.h>
+
+namespace aidl::android::hardware::thermal {
+
+namespace {
+
+using ::android::sp;
+using android::hardware::thermal::CoolingDevice;
+using android::hardware::thermal::IThermal;
+using android::hardware::thermal::Temperature;
+using android::hardware::thermal::TemperatureType;
+
+using namespace std::string_literals;
+using namespace std::chrono_literals;
+
+static const Temperature kThrottleTemp = {
+        .type = TemperatureType::SKIN,
+        .name = "test temperature sensor",
+        .value = 98.6,
+        .throttlingStatus = ThrottlingSeverity::CRITICAL,
+};
+
+// Callback class for receiving thermal event notifications from main class
+class ThermalCallback : public BnThermalChangedCallback {
+  public:
+    ndk::ScopedAStatus notifyThrottling(const Temperature&) override {
+        {
+            std::lock_guard<std::mutex> lock(mMutex);
+            mInvoke = true;
+        }
+        mNotifyThrottling.notify_all();
+        return ndk::ScopedAStatus::ok();
+    }
+
+    template <typename R, typename P>
+    [[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
+        std::unique_lock<std::mutex> lock(mMutex);
+        bool r = mNotifyThrottling.wait_for(lock, duration, [this] { return this->mInvoke; });
+        mInvoke = false;
+        return r;
+    }
+
+  private:
+    std::mutex mMutex;
+    std::condition_variable mNotifyThrottling;
+    bool mInvoke = false;
+};
+
+// The main test class for THERMAL HIDL HAL.
+class ThermalAidlTest : public testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override {
+        AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
+        ASSERT_NE(binder, nullptr);
+        mThermal = IThermal::fromBinder(ndk::SpAIBinder(binder));
+
+        mThermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
+        ASSERT_NE(mThermalCallback, nullptr);
+        auto ret = mThermal->registerThermalChangedCallback(mThermalCallback);
+        ASSERT_TRUE(ret.isOk());
+        // Expect to fail if register again
+        ret = mThermal->registerThermalChangedCallback(mThermalCallback);
+        ASSERT_FALSE(ret.isOk());
+        ASSERT_TRUE(ret.getStatus() == STATUS_INVALID_OPERATION);
+    }
+
+    void TearDown() override {
+        auto ret = mThermal->unregisterThermalChangedCallback(mThermalCallback);
+        ASSERT_TRUE(ret.isOk());
+        // Expect to fail if unregister again
+        ret = mThermal->unregisterThermalChangedCallback(mThermalCallback);
+        ASSERT_FALSE(ret.isOk());
+        ASSERT_TRUE(ret.getStatus() == STATUS_INVALID_OPERATION);
+    }
+
+  protected:
+    std::shared_ptr<IThermal> mThermal;
+    std::shared_ptr<ThermalCallback> mThermalCallback;
+};
+
+// Test ThermalChangedCallback::notifyThrottling().
+// This just calls into and back from our local ThermalChangedCallback impl.
+TEST_P(ThermalAidlTest, NotifyThrottlingTest) {
+    std::shared_ptr<ThermalCallback> thermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
+    auto ret = thermalCallback->notifyThrottling(kThrottleTemp);
+    ASSERT_TRUE(ret.isOk());
+    ASSERT_TRUE(thermalCallback->waitForCallback(200ms));
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+        Thermal, ThermalAidlTest,
+        testing::ValuesIn(::android::getAidlHalInstanceNames(IThermal::descriptor)),
+        ::android::PrintInstanceNameToString);
+
+}  // namespace
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
+
+}  // namespace aidl::android::hardware::thermal
diff --git a/tv/cec/aidl/Android.bp b/tv/cec/aidl/Android.bp
new file mode 100644
index 0000000..0b0e7cf
--- /dev/null
+++ b/tv/cec/aidl/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.tv.cec",
+    vendor_available: true,
+    srcs: ["android/hardware/tv/cec/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            sdk_version: "module_current",
+        },
+    },
+}
diff --git a/tv/cec/aidl/OWNERS b/tv/cec/aidl/OWNERS
new file mode 100644
index 0000000..d9c6783
--- /dev/null
+++ b/tv/cec/aidl/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 826094
+include platform/frameworks/base:/core/java/android/hardware/hdmi/OWNERS
\ No newline at end of file
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/AbortReason.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/AbortReason.aidl
new file mode 100644
index 0000000..7377d81
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/AbortReason.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.cec;
+@Backing(type="int") @VintfStability
+enum AbortReason {
+  UNRECOGNIZED_MODE = 0,
+  NOT_IN_CORRECT_MODE = 1,
+  CANNOT_PROVIDE_SOURCE = 2,
+  INVALID_OPERAND = 3,
+  REFUSED = 4,
+  UNABLE_TO_DETERMINE = 5,
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecDeviceType.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecDeviceType.aidl
new file mode 100644
index 0000000..4d991cd
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecDeviceType.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.cec;
+@Backing(type="byte") @VintfStability
+enum CecDeviceType {
+  INACTIVE = -1,
+  TV = 0,
+  RECORDER = 1,
+  TUNER = 3,
+  PLAYBACK = 4,
+  AUDIO_SYSTEM = 5,
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecLogicalAddress.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecLogicalAddress.aidl
new file mode 100644
index 0000000..a36935b
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecLogicalAddress.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.cec;
+@Backing(type="byte") @VintfStability
+enum CecLogicalAddress {
+  TV = 0,
+  RECORDER_1 = 1,
+  RECORDER_2 = 2,
+  TUNER_1 = 3,
+  PLAYBACK_1 = 4,
+  AUDIO_SYSTEM = 5,
+  TUNER_2 = 6,
+  TUNER_3 = 7,
+  PLAYBACK_2 = 8,
+  RECORDER_3 = 9,
+  TUNER_4 = 10,
+  PLAYBACK_3 = 11,
+  BACKUP_1 = 12,
+  BACKUP_2 = 13,
+  FREE_USE = 14,
+  BROADCAST = 15,
+  UNREGISTERED = 15,
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessage.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessage.aidl
new file mode 100644
index 0000000..5ce5ce8
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessage.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.cec;
+@VintfStability
+parcelable CecMessage {
+  android.hardware.tv.cec.CecLogicalAddress initiator;
+  android.hardware.tv.cec.CecLogicalAddress destination;
+  byte[] body;
+  const int MAX_MESSAGE_BODY_LENGTH = 15;
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessageType.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessageType.aidl
new file mode 100644
index 0000000..61ebb94
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessageType.aidl
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.cec;
+@Backing(type="int") @VintfStability
+enum CecMessageType {
+  FEATURE_ABORT = 0,
+  IMAGE_VIEW_ON = 4,
+  TUNER_STEP_INCREMENT = 5,
+  TUNER_STEP_DECREMENT = 6,
+  TUNER_DEVICE_STATUS = 7,
+  GIVE_TUNER_DEVICE_STATUS = 8,
+  RECORD_ON = 9,
+  RECORD_STATUS = 10,
+  RECORD_OFF = 11,
+  TEXT_VIEW_ON = 13,
+  RECORD_TV_SCREEN = 15,
+  GIVE_DECK_STATUS = 26,
+  DECK_STATUS = 27,
+  SET_MENU_LANGUAGE = 50,
+  CLEAR_ANALOG_TIMER = 51,
+  SET_ANALOG_TIMER = 52,
+  TIMER_STATUS = 53,
+  STANDBY = 54,
+  PLAY = 65,
+  DECK_CONTROL = 66,
+  TIMER_CLEARED_STATUS = 67,
+  USER_CONTROL_PRESSED = 68,
+  USER_CONTROL_RELEASED = 69,
+  GIVE_OSD_NAME = 70,
+  SET_OSD_NAME = 71,
+  SET_OSD_STRING = 100,
+  SET_TIMER_PROGRAM_TITLE = 103,
+  SYSTEM_AUDIO_MODE_REQUEST = 112,
+  GIVE_AUDIO_STATUS = 113,
+  SET_SYSTEM_AUDIO_MODE = 114,
+  REPORT_AUDIO_STATUS = 122,
+  GIVE_SYSTEM_AUDIO_MODE_STATUS = 125,
+  SYSTEM_AUDIO_MODE_STATUS = 126,
+  ROUTING_CHANGE = 128,
+  ROUTING_INFORMATION = 129,
+  ACTIVE_SOURCE = 130,
+  GIVE_PHYSICAL_ADDRESS = 131,
+  REPORT_PHYSICAL_ADDRESS = 132,
+  REQUEST_ACTIVE_SOURCE = 133,
+  SET_STREAM_PATH = 134,
+  DEVICE_VENDOR_ID = 135,
+  VENDOR_COMMAND = 137,
+  VENDOR_REMOTE_BUTTON_DOWN = 138,
+  VENDOR_REMOTE_BUTTON_UP = 139,
+  GIVE_DEVICE_VENDOR_ID = 140,
+  MENU_REQUEST = 141,
+  MENU_STATUS = 142,
+  GIVE_DEVICE_POWER_STATUS = 143,
+  REPORT_POWER_STATUS = 144,
+  GET_MENU_LANGUAGE = 145,
+  SELECT_ANALOG_SERVICE = 146,
+  SELECT_DIGITAL_SERVICE = 147,
+  SET_DIGITAL_TIMER = 151,
+  CLEAR_DIGITAL_TIMER = 153,
+  SET_AUDIO_RATE = 154,
+  INACTIVE_SOURCE = 157,
+  CEC_VERSION = 158,
+  GET_CEC_VERSION = 159,
+  VENDOR_COMMAND_WITH_ID = 160,
+  CLEAR_EXTERNAL_TIMER = 161,
+  SET_EXTERNAL_TIMER = 162,
+  REPORT_SHORT_AUDIO_DESCRIPTOR = 163,
+  REQUEST_SHORT_AUDIO_DESCRIPTOR = 164,
+  INITIATE_ARC = 192,
+  REPORT_ARC_INITIATED = 193,
+  REPORT_ARC_TERMINATED = 194,
+  REQUEST_ARC_INITIATION = 195,
+  REQUEST_ARC_TERMINATION = 196,
+  TERMINATE_ARC = 197,
+  ABORT = 255,
+  GIVE_FEATURES = 165,
+  REPORT_FEATURES = 166,
+  REQUEST_CURRENT_LATENCY = 167,
+  REPORT_CURRENT_LATENCY = 168,
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCec.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCec.aidl
new file mode 100644
index 0000000..cf8425e
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCec.aidl
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.cec;
+@VintfStability
+interface IHdmiCec {
+  android.hardware.tv.cec.Result addLogicalAddress(in android.hardware.tv.cec.CecLogicalAddress addr);
+  void clearLogicalAddress();
+  void enableAudioReturnChannel(in int portId, in boolean enable);
+  int getCecVersion();
+  int getPhysicalAddress();
+  int getVendorId();
+  android.hardware.tv.cec.SendMessageResult sendMessage(in android.hardware.tv.cec.CecMessage message);
+  void setCallback(in android.hardware.tv.cec.IHdmiCecCallback callback);
+  void setLanguage(in String language);
+  void enableWakeupByOtp(in boolean value);
+  void enableCec(in boolean value);
+  void enableSystemCecControl(in boolean value);
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCecCallback.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCecCallback.aidl
new file mode 100644
index 0000000..1918765
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCecCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.cec;
+@VintfStability
+interface IHdmiCecCallback {
+  oneway void onCecMessage(in android.hardware.tv.cec.CecMessage message);
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/Result.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/Result.aidl
new file mode 100644
index 0000000..a5ba276
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/Result.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.cec;
+@Backing(type="byte") @VintfStability
+enum Result {
+  SUCCESS = 0,
+  FAILURE_UNKNOWN = 1,
+  FAILURE_INVALID_ARGS = 2,
+  FAILURE_INVALID_STATE = 3,
+  FAILURE_NOT_SUPPORTED = 4,
+  FAILURE_BUSY = 5,
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/SendMessageResult.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/SendMessageResult.aidl
new file mode 100644
index 0000000..58206c8
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/SendMessageResult.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.cec;
+@Backing(type="byte") @VintfStability
+enum SendMessageResult {
+  SUCCESS = 0,
+  NACK = 1,
+  BUSY = 2,
+  FAIL = 3,
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/AbortReason.aidl b/tv/cec/aidl/android/hardware/tv/cec/AbortReason.aidl
new file mode 100644
index 0000000..3ae23ec
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/AbortReason.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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.tv.cec;
+
+/**
+ * Operand description [Abort Reason]
+ */
+@VintfStability
+@Backing(type="int")
+enum AbortReason {
+    UNRECOGNIZED_MODE = 0,
+    NOT_IN_CORRECT_MODE = 1,
+    CANNOT_PROVIDE_SOURCE = 2,
+    INVALID_OPERAND = 3,
+    REFUSED = 4,
+    UNABLE_TO_DETERMINE = 5,
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/CecDeviceType.aidl b/tv/cec/aidl/android/hardware/tv/cec/CecDeviceType.aidl
new file mode 100644
index 0000000..16dfbec
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/CecDeviceType.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.tv.cec;
+
+@VintfStability
+@Backing(type="byte")
+enum CecDeviceType {
+    INACTIVE = -1,
+    TV = 0,
+    RECORDER = 1,
+    TUNER = 3,
+    PLAYBACK = 4,
+    AUDIO_SYSTEM = 5,
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/CecLogicalAddress.aidl b/tv/cec/aidl/android/hardware/tv/cec/CecLogicalAddress.aidl
new file mode 100644
index 0000000..fbf5328
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/CecLogicalAddress.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.tv.cec;
+
+@VintfStability
+@Backing(type="byte")
+enum CecLogicalAddress {
+    TV = 0,
+    RECORDER_1 = 1,
+    RECORDER_2 = 2,
+    TUNER_1 = 3,
+    PLAYBACK_1 = 4,
+    AUDIO_SYSTEM = 5,
+    TUNER_2 = 6,
+    TUNER_3 = 7,
+    PLAYBACK_2 = 8,
+    RECORDER_3 = 9,
+    TUNER_4 = 10,
+    PLAYBACK_3 = 11,
+    BACKUP_1 = 12,
+    BACKUP_2 = 13,
+    FREE_USE = 14,
+    BROADCAST = 15,
+    UNREGISTERED = 15,
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/CecMessage.aidl b/tv/cec/aidl/android/hardware/tv/cec/CecMessage.aidl
new file mode 100644
index 0000000..b126045
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/CecMessage.aidl
@@ -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 android.hardware.tv.cec;
+
+import android.hardware.tv.cec.CecLogicalAddress;
+
+@VintfStability
+parcelable CecMessage {
+    /**
+     * Maximum length of the message body
+     */
+    const int MAX_MESSAGE_BODY_LENGTH = 15;
+    /**
+     * logical address of the initiator
+     */
+    CecLogicalAddress initiator;
+    /**
+     * logical address of destination
+     */
+    CecLogicalAddress destination;
+    /**
+     * The maximum size of body is 15 (MAX_MESSAGE_BODY_LENGTH) as specified in
+     * the section 6 of the CEC Spec 1.4b. Overflowed data must be ignored.
+     */
+    byte[] body;
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/CecMessageType.aidl b/tv/cec/aidl/android/hardware/tv/cec/CecMessageType.aidl
new file mode 100644
index 0000000..b544a91
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/CecMessageType.aidl
@@ -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.
+ */
+
+package android.hardware.tv.cec;
+
+@VintfStability
+@Backing(type="int")
+enum CecMessageType {
+    FEATURE_ABORT = 0x00,
+    IMAGE_VIEW_ON = 0x04,
+    TUNER_STEP_INCREMENT = 0x05,
+    TUNER_STEP_DECREMENT = 0x06,
+    TUNER_DEVICE_STATUS = 0x07,
+    GIVE_TUNER_DEVICE_STATUS = 0x08,
+    RECORD_ON = 0x09,
+    RECORD_STATUS = 0x0A,
+    RECORD_OFF = 0x0B,
+    TEXT_VIEW_ON = 0x0D,
+    RECORD_TV_SCREEN = 0x0F,
+    GIVE_DECK_STATUS = 0x1A,
+    DECK_STATUS = 0x1B,
+    SET_MENU_LANGUAGE = 0x32,
+    CLEAR_ANALOG_TIMER = 0x33,
+    SET_ANALOG_TIMER = 0x34,
+    TIMER_STATUS = 0x35,
+    STANDBY = 0x36,
+    PLAY = 0x41,
+    DECK_CONTROL = 0x42,
+    TIMER_CLEARED_STATUS = 0x43,
+    USER_CONTROL_PRESSED = 0x44,
+    USER_CONTROL_RELEASED = 0x45,
+    GIVE_OSD_NAME = 0x46,
+    SET_OSD_NAME = 0x47,
+    SET_OSD_STRING = 0x64,
+    SET_TIMER_PROGRAM_TITLE = 0x67,
+    SYSTEM_AUDIO_MODE_REQUEST = 0x70,
+    GIVE_AUDIO_STATUS = 0x71,
+    SET_SYSTEM_AUDIO_MODE = 0x72,
+    REPORT_AUDIO_STATUS = 0x7A,
+    GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D,
+    SYSTEM_AUDIO_MODE_STATUS = 0x7E,
+    ROUTING_CHANGE = 0x80,
+    ROUTING_INFORMATION = 0x81,
+    ACTIVE_SOURCE = 0x82,
+    GIVE_PHYSICAL_ADDRESS = 0x83,
+    REPORT_PHYSICAL_ADDRESS = 0x84,
+    REQUEST_ACTIVE_SOURCE = 0x85,
+    SET_STREAM_PATH = 0x86,
+    DEVICE_VENDOR_ID = 0x87,
+    VENDOR_COMMAND = 0x89,
+    VENDOR_REMOTE_BUTTON_DOWN = 0x8A,
+    VENDOR_REMOTE_BUTTON_UP = 0x8B,
+    GIVE_DEVICE_VENDOR_ID = 0x8C,
+    MENU_REQUEST = 0x8D,
+    MENU_STATUS = 0x8E,
+    GIVE_DEVICE_POWER_STATUS = 0x8F,
+    REPORT_POWER_STATUS = 0x90,
+    GET_MENU_LANGUAGE = 0x91,
+    SELECT_ANALOG_SERVICE = 0x92,
+    SELECT_DIGITAL_SERVICE = 0x93,
+    SET_DIGITAL_TIMER = 0x97,
+    CLEAR_DIGITAL_TIMER = 0x99,
+    SET_AUDIO_RATE = 0x9A,
+    INACTIVE_SOURCE = 0x9D,
+    CEC_VERSION = 0x9E,
+    GET_CEC_VERSION = 0x9F,
+    VENDOR_COMMAND_WITH_ID = 0xA0,
+    CLEAR_EXTERNAL_TIMER = 0xA1,
+    SET_EXTERNAL_TIMER = 0xA2,
+    REPORT_SHORT_AUDIO_DESCRIPTOR = 0xA3,
+    REQUEST_SHORT_AUDIO_DESCRIPTOR = 0xA4,
+    INITIATE_ARC = 0xC0,
+    REPORT_ARC_INITIATED = 0xC1,
+    REPORT_ARC_TERMINATED = 0xC2,
+    REQUEST_ARC_INITIATION = 0xC3,
+    REQUEST_ARC_TERMINATION = 0xC4,
+    TERMINATE_ARC = 0xC5,
+    ABORT = 0xFF,
+    GIVE_FEATURES = 0xA5,
+    REPORT_FEATURES = 0xA6,
+    REQUEST_CURRENT_LATENCY = 0xA7,
+    REPORT_CURRENT_LATENCY = 0xA8,
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/IHdmiCec.aidl b/tv/cec/aidl/android/hardware/tv/cec/IHdmiCec.aidl
new file mode 100644
index 0000000..dbf7139
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/IHdmiCec.aidl
@@ -0,0 +1,156 @@
+/*
+ * 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.tv.cec;
+
+import android.hardware.tv.cec.CecLogicalAddress;
+import android.hardware.tv.cec.CecMessage;
+import android.hardware.tv.cec.IHdmiCecCallback;
+import android.hardware.tv.cec.Result;
+import android.hardware.tv.cec.SendMessageResult;
+
+/**
+ * HDMI-CEC HAL interface definition.
+ */
+@VintfStability
+interface IHdmiCec {
+    /**
+     * Passes the logical address that must be used in this system.
+     *
+     * HAL must use it to configure the hardware so that the CEC commands
+     * addressed the given logical address can be filtered in. This method must
+     * be able to be called as many times as necessary in order to support
+     * multiple logical devices.
+     *
+     * @param addr Logical address that must be used in this system. It must be
+     *        in the range of valid logical addresses for the call to succeed.
+     * @return Result status of the operation. SUCCESS if successful,
+     *         FAILURE_INVALID_ARGS if the given logical address is invalid,
+     *         FAILURE_BUSY if device or resource is busy
+     */
+    Result addLogicalAddress(in CecLogicalAddress addr);
+
+    /**
+     * Clears all the logical addresses.
+     *
+     * It is used when the system doesn't need to process CEC command any more,
+     * hence to tell HAL to stop receiving commands from the CEC bus, and change
+     * the state back to the beginning.
+     */
+    void clearLogicalAddress();
+
+    /**
+     * Configures ARC circuit in the hardware logic to start or stop the
+     * feature.
+     *
+     * @param portId Port id to be configured.
+     * @param enable Flag must be either true to start the feature or false to
+     *        stop it.
+     */
+    void enableAudioReturnChannel(in int portId, in boolean enable);
+
+    /**
+     * Returns the CEC version supported by underlying hardware.
+     *
+     * @return the CEC version supported by underlying hardware.
+     */
+    int getCecVersion();
+
+    /**
+     * Gets the CEC physical address.
+     *
+     * The physical address depends on the topology of the network formed by
+     * connected HDMI devices. It is therefore likely to change if the cable is
+     * plugged off and on again. It is advised to call getPhysicalAddress to get
+     * the updated address when hot plug event takes place.
+     *
+     * @param out addr Physical address of this device.
+     */
+    int getPhysicalAddress();
+
+    /**
+     * Gets the identifier of the vendor.
+     *
+     * @return Identifier of the vendor that is the 24-bit unique
+     *         company ID obtained from the IEEE Registration Authority
+     *         Committee (RAC). The upper 8 bits must be 0.
+     */
+    int getVendorId();
+
+    /**
+     * Transmits HDMI-CEC message to other HDMI device.
+     *
+     * The method must be designed to return in a certain amount of time and not
+     * hanging forever which may happen if CEC signal line is pulled low for
+     * some reason.
+     *
+     * It must try retransmission at least once as specified in the section '7.1
+     * Frame Re-transmissions' of the CEC Spec 1.4b.
+     *
+     * @param message CEC message to be sent to other HDMI device.
+     * @return Result status of the operation. SUCCESS if successful,
+     *         NACK if the sent message is not acknowledged,
+     *         BUSY if the CEC bus is busy,
+     *         FAIL if the message could not be sent.
+     */
+    SendMessageResult sendMessage(in CecMessage message);
+
+    /**
+     * Sets a callback that HDMI-CEC HAL must later use for incoming CEC
+     * messages.
+     *
+     * @param callback Callback object to pass hdmi events to the system. The
+     *        previously registered callback must be replaced with this one.
+     *        setCallback(null) should deregister the callback.
+     */
+    void setCallback(in IHdmiCecCallback callback);
+
+    /**
+     * Passes the updated language information of Android system. Contains
+     * three-letter code as defined in ISO/FDIS 639-2. Must be used for HAL to
+     * respond to <Get Menu Language> while in standby mode.
+     *
+     * @param language Three-letter code defined in ISO/FDIS 639-2. Must be
+     *        lowercase letters. (e.g., eng for English)
+     */
+    void setLanguage(in String language);
+
+    /**
+     * Determines whether a TV panel device in standby mode should wake up when
+     * it receives an OTP (One Touch Play) from a source device.
+     *
+     * @param value If true, the TV device will wake up when OTP is received
+     *              and if false, the TV device will not wake up for an OTP.
+     */
+    void enableWakeupByOtp(in boolean value);
+
+    /**
+     * Switch to enable or disable CEC on the device.
+     *
+     * @param value If true, the device will have all CEC functionalities
+     *              and if false, the device will not perform any CEC functions.
+     */
+    void enableCec(in boolean value);
+
+    /**
+     * Determines which module processes CEC messages - the Android framework or
+     * the HAL.
+     *
+     * @param value If true, the Android framework will actively process CEC
+     *        messages and if false, only the HAL will process the CEC messages.
+     */
+    void enableSystemCecControl(in boolean value);
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/IHdmiCecCallback.aidl b/tv/cec/aidl/android/hardware/tv/cec/IHdmiCecCallback.aidl
new file mode 100644
index 0000000..4934a64
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/IHdmiCecCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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.tv.cec;
+
+import android.hardware.tv.cec.CecMessage;
+
+/**
+ * Callbacks from the HAL implementation to notify the system of new events.
+ */
+@VintfStability
+oneway interface IHdmiCecCallback {
+    /**
+     * The callback function that must be called by HAL implementation to notify
+     * the system of new CEC message arrival.
+     */
+    void onCecMessage(in CecMessage message);
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/Result.aidl b/tv/cec/aidl/android/hardware/tv/cec/Result.aidl
new file mode 100644
index 0000000..3184c46
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/Result.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.tv.cec;
+
+@VintfStability
+@Backing(type="byte")
+enum Result {
+    SUCCESS = 0,
+    FAILURE_UNKNOWN = 1,
+    FAILURE_INVALID_ARGS = 2,
+    FAILURE_INVALID_STATE = 3,
+    FAILURE_NOT_SUPPORTED = 4,
+    FAILURE_BUSY = 5,
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/SendMessageResult.aidl b/tv/cec/aidl/android/hardware/tv/cec/SendMessageResult.aidl
new file mode 100644
index 0000000..8cb98bc
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/SendMessageResult.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.tv.cec;
+
+/**
+ * error code used for send_message.
+ */
+@VintfStability
+@Backing(type="byte")
+enum SendMessageResult {
+    SUCCESS = 0,
+    NACK = 1,
+    BUSY = 2,
+    FAIL = 3,
+}
diff --git a/tv/cec/aidl/default/Android.bp b/tv/cec/aidl/default/Android.bp
new file mode 100644
index 0000000..5479601
--- /dev/null
+++ b/tv/cec/aidl/default/Android.bp
@@ -0,0 +1,58 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_binary {
+    name: "android.hardware.tv.cec-service",
+    vintf_fragments: ["android.hardware.tv.cec-service.xml"],
+    relative_install_path: "hw",
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+    ],
+    init_rc: ["android.hardware.tv.cec-service.rc"],
+    srcs: [
+        "serviceMock.cpp",
+        "HdmiCecMock.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "liblog",
+        "libbase",
+        "libutils",
+        "libhardware",
+        "libhidlbase",
+        "android.hardware.tv.cec-V1-ndk",
+    ],
+}
+
+cc_fuzz {
+    name: "android.hardware.tv.cec-service_fuzzer",
+    defaults: ["service_fuzzer_defaults"],
+    static_libs: [
+        "android.hardware.tv.cec-V1-ndk",
+        "liblog",
+    ],
+    srcs: [
+        "fuzzer.cpp",
+        "HdmiCecMock.cpp",
+    ],
+    fuzz_config: {
+        componentid: 826094,
+    },
+}
diff --git a/tv/cec/aidl/default/HdmiCecMock.cpp b/tv/cec/aidl/default/HdmiCecMock.cpp
new file mode 100644
index 0000000..d8d655b
--- /dev/null
+++ b/tv/cec/aidl/default/HdmiCecMock.cpp
@@ -0,0 +1,266 @@
+/*
+ * 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 "android.hardware.tv.cec"
+#include <android-base/logging.h>
+#include <fcntl.h>
+#include <utils/Log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/hdmi_cec.h>
+#include "HdmiCecMock.h"
+
+using ndk::ScopedAStatus;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace cec {
+namespace implementation {
+
+void HdmiCecMock::serviceDied(void* cookie) {
+    ALOGE("HdmiCecMock died");
+    auto hdmiCecMock = static_cast<HdmiCecMock*>(cookie);
+    hdmiCecMock->mCecThreadRun = false;
+}
+
+ScopedAStatus HdmiCecMock::addLogicalAddress(CecLogicalAddress addr, Result* _aidl_return) {
+    // Have a list to maintain logical addresses
+    mLogicalAddresses.push_back(addr);
+    *_aidl_return = Result::SUCCESS;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::clearLogicalAddress() {
+    // Remove logical address from the list
+    mLogicalAddresses = {};
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::enableAudioReturnChannel(int32_t portId __unused, bool enable __unused) {
+    // Maintain ARC status
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::getCecVersion(int32_t* _aidl_return) {
+    // Maintain a cec version and return it
+    *_aidl_return = mCecVersion;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::getPhysicalAddress(int32_t* _aidl_return) {
+    // Maintain a physical address and return it
+    // Default 0xFFFF, update on hotplug event
+    *_aidl_return = mPhysicalAddress;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::getVendorId(int32_t* _aidl_return) {
+    *_aidl_return = mCecVendorId;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::sendMessage(const CecMessage& message, SendMessageResult* _aidl_return) {
+    if (message.body.size() == 0) {
+        *_aidl_return = SendMessageResult::NACK;
+    } else {
+        sendMessageToFifo(message);
+        *_aidl_return = SendMessageResult::SUCCESS;
+    }
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::setCallback(const std::shared_ptr<IHdmiCecCallback>& callback) {
+    // If callback is null, mCallback is also set to null so we do not call the old callback.
+    mCallback = callback;
+
+    if (callback != nullptr) {
+        AIBinder_linkToDeath(this->asBinder().get(), mDeathRecipient.get(), 0 /* cookie */);
+
+        mInputFile = open(CEC_MSG_IN_FIFO, O_RDWR | O_CLOEXEC);
+        mOutputFile = open(CEC_MSG_OUT_FIFO, O_RDWR | O_CLOEXEC);
+        pthread_create(&mThreadId, NULL, __threadLoop, this);
+        pthread_setname_np(mThreadId, "hdmi_cec_loop");
+    }
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::setLanguage(const std::string& language) {
+    if (language.size() != 3) {
+        LOG(ERROR) << "Wrong language code: expected 3 letters, but it was " << language.size()
+                   << ".";
+        return ScopedAStatus::ok();
+    }
+    // TODO Validate if language is a valid language code
+    const char* languageStr = language.c_str();
+    int convertedLanguage = ((languageStr[0] & 0xFF) << 16) | ((languageStr[1] & 0xFF) << 8) |
+                            (languageStr[2] & 0xFF);
+    mOptionLanguage = convertedLanguage;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::enableWakeupByOtp(bool value) {
+    mOptionWakeUp = value;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::enableCec(bool value) {
+    mOptionEnableCec = value;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::enableSystemCecControl(bool value) {
+    mOptionSystemCecControl = value;
+    return ScopedAStatus::ok();
+}
+
+void* HdmiCecMock::__threadLoop(void* user) {
+    HdmiCecMock* const self = static_cast<HdmiCecMock*>(user);
+    self->threadLoop();
+    return 0;
+}
+
+int HdmiCecMock::readMessageFromFifo(unsigned char* buf, int msgCount) {
+    if (msgCount <= 0 || !buf) {
+        return 0;
+    }
+
+    int ret = -1;
+    // Maybe blocked at driver
+    ret = read(mInputFile, buf, msgCount);
+    if (ret < 0) {
+        ALOGE("[halimp_aidl] read :%s failed, ret:%d\n", CEC_MSG_IN_FIFO, ret);
+        return -1;
+    }
+
+    return ret;
+}
+
+int HdmiCecMock::sendMessageToFifo(const CecMessage& message) {
+    unsigned char msgBuf[CEC_MESSAGE_BODY_MAX_LENGTH + 1] = {0};
+    int ret = -1;
+
+    msgBuf[0] = ((static_cast<uint8_t>(message.initiator) & 0xf) << 4) |
+                (static_cast<uint8_t>(message.destination) & 0xf);
+
+    size_t length = std::min(static_cast<size_t>(message.body.size()),
+                             static_cast<size_t>(CEC_MESSAGE_BODY_MAX_LENGTH));
+    for (size_t i = 0; i < length; ++i) {
+        msgBuf[i + 1] = static_cast<unsigned char>(message.body[i]);
+    }
+
+    // Open the output pipe for writing outgoing cec message
+    mOutputFile = open(CEC_MSG_OUT_FIFO, O_WRONLY | O_CLOEXEC);
+    if (mOutputFile < 0) {
+        ALOGD("[halimp_aidl] file open failed for writing");
+        return -1;
+    }
+
+    // Write message into the output pipe
+    ret = write(mOutputFile, msgBuf, length + 1);
+    close(mOutputFile);
+    if (ret < 0) {
+        ALOGE("[halimp_aidl] write :%s failed, ret:%d\n", CEC_MSG_OUT_FIFO, ret);
+        return -1;
+    }
+    return ret;
+}
+
+void HdmiCecMock::printCecMsgBuf(const char* msg_buf, int len) {
+    int i, size = 0;
+    const int bufSize = CEC_MESSAGE_BODY_MAX_LENGTH * 3;
+    // Use 2 characters for each byte in the message plus 1 space
+    char buf[bufSize] = {0};
+
+    // Messages longer than max length will be truncated.
+    for (i = 0; i < len && size < bufSize; i++) {
+        size += sprintf(buf + size, " %02x", msg_buf[i]);
+    }
+    ALOGD("[halimp_aidl] %s, msg:%.*s", __FUNCTION__, size, buf);
+}
+
+void HdmiCecMock::handleCecMessage(unsigned char* msgBuf, int msgSize) {
+    CecMessage message;
+    size_t length = std::min(static_cast<size_t>(msgSize - 1),
+                             static_cast<size_t>(CEC_MESSAGE_BODY_MAX_LENGTH));
+    message.body.resize(length);
+
+    for (size_t i = 0; i < length; ++i) {
+        message.body[i] = static_cast<uint8_t>(msgBuf[i + 1]);
+        ALOGD("[halimp_aidl] msg body %x", message.body[i]);
+    }
+
+    message.initiator = static_cast<CecLogicalAddress>((msgBuf[0] >> 4) & 0xf);
+    ALOGD("[halimp_aidl] msg init %hhd", message.initiator);
+    message.destination = static_cast<CecLogicalAddress>((msgBuf[0] >> 0) & 0xf);
+    ALOGD("[halimp_aidl] msg dest %hhd", message.destination);
+
+    if (mCallback != nullptr) {
+        mCallback->onCecMessage(message);
+    }
+}
+
+void HdmiCecMock::threadLoop() {
+    ALOGD("[halimp_aidl] threadLoop start.");
+    unsigned char msgBuf[CEC_MESSAGE_BODY_MAX_LENGTH];
+    int r = -1;
+
+    // Open the input pipe
+    while (mInputFile < 0) {
+        usleep(1000 * 1000);
+        mInputFile = open(CEC_MSG_IN_FIFO, O_RDONLY | O_CLOEXEC);
+    }
+    ALOGD("[halimp_aidl] file open ok, fd = %d.", mInputFile);
+
+    while (mCecThreadRun) {
+        if (!mOptionSystemCecControl) {
+            usleep(1000 * 1000);
+            continue;
+        }
+
+        memset(msgBuf, 0, sizeof(msgBuf));
+        // Try to get a message from dev.
+        // echo -n -e '\x04\x83' >> /dev/cec
+        r = readMessageFromFifo(msgBuf, CEC_MESSAGE_BODY_MAX_LENGTH);
+        if (r <= 1) {
+            // Ignore received ping messages
+            continue;
+        }
+
+        printCecMsgBuf((const char*)msgBuf, r);
+
+        if (((msgBuf[0] >> 4) & 0xf) == 0xf) {
+            // The message is a hotplug event, handled by HDMI HAL.
+            continue;
+        }
+
+        handleCecMessage(msgBuf, r);
+    }
+
+    ALOGD("[halimp_aidl] thread end.");
+}
+
+HdmiCecMock::HdmiCecMock() {
+    ALOGE("[halimp_aidl] Opening a virtual CEC HAL for testing and virtual machine.");
+    mCallback = nullptr;
+    mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(serviceDied));
+}
+
+}  // namespace implementation
+}  // namespace cec
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/cec/aidl/default/HdmiCecMock.h b/tv/cec/aidl/default/HdmiCecMock.h
new file mode 100644
index 0000000..08f4d6f
--- /dev/null
+++ b/tv/cec/aidl/default/HdmiCecMock.h
@@ -0,0 +1,94 @@
+/*
+ * 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/android/hardware/tv/cec/BnHdmiCec.h>
+#include <algorithm>
+#include <vector>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace cec {
+namespace implementation {
+
+using ::aidl::android::hardware::tv::cec::BnHdmiCec;
+using ::aidl::android::hardware::tv::cec::CecLogicalAddress;
+using ::aidl::android::hardware::tv::cec::CecMessage;
+using ::aidl::android::hardware::tv::cec::IHdmiCec;
+using ::aidl::android::hardware::tv::cec::IHdmiCecCallback;
+using ::aidl::android::hardware::tv::cec::Result;
+using ::aidl::android::hardware::tv::cec::SendMessageResult;
+
+#define CEC_MSG_IN_FIFO "/dev/cec_aidl_in_pipe"
+#define CEC_MSG_OUT_FIFO "/dev/cec_aidl_out_pipe"
+
+struct HdmiCecMock : public BnHdmiCec {
+    HdmiCecMock();
+    ::ndk::ScopedAStatus addLogicalAddress(CecLogicalAddress addr, Result* _aidl_return) override;
+    ::ndk::ScopedAStatus clearLogicalAddress() override;
+    ::ndk::ScopedAStatus enableAudioReturnChannel(int32_t portId, bool enable) override;
+    ::ndk::ScopedAStatus getCecVersion(int32_t* _aidl_return) override;
+    ::ndk::ScopedAStatus getPhysicalAddress(int32_t* _aidl_return) override;
+    ::ndk::ScopedAStatus getVendorId(int32_t* _aidl_return) override;
+    ::ndk::ScopedAStatus sendMessage(const CecMessage& message,
+                                     SendMessageResult* _aidl_return) override;
+    ::ndk::ScopedAStatus setCallback(const std::shared_ptr<IHdmiCecCallback>& callback) override;
+    ::ndk::ScopedAStatus setLanguage(const std::string& language) override;
+    ::ndk::ScopedAStatus enableWakeupByOtp(bool value) override;
+    ::ndk::ScopedAStatus enableCec(bool value) override;
+    ::ndk::ScopedAStatus enableSystemCecControl(bool value) override;
+    void printCecMsgBuf(const char* msg_buf, int len);
+
+  private:
+    static void* __threadLoop(void* data);
+    void threadLoop();
+    int readMessageFromFifo(unsigned char* buf, int msgCount);
+    int sendMessageToFifo(const CecMessage& message);
+    void handleCecMessage(unsigned char* msgBuf, int length);
+
+  private:
+    static void serviceDied(void* cookie);
+    std::shared_ptr<IHdmiCecCallback> mCallback;
+
+    // Variables for the virtual cec hal impl
+    uint16_t mPhysicalAddress = 0xFFFF;
+    vector<CecLogicalAddress> mLogicalAddresses;
+    int32_t mCecVersion = 0x06;
+    uint32_t mCecVendorId = 0x01;
+
+    // CEC Option value
+    bool mOptionWakeUp = 0;
+    bool mOptionEnableCec = 0;
+    bool mOptionSystemCecControl = 0;
+    int mOptionLanguage;
+
+    // Testing variables
+    // Input file descriptor
+    int mInputFile;
+    // Output file descriptor
+    int mOutputFile;
+    bool mCecThreadRun = true;
+    pthread_t mThreadId = 0;
+
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+};
+}  // namespace implementation
+}  // namespace cec
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/cec/aidl/default/android.hardware.tv.cec-service.rc b/tv/cec/aidl/default/android.hardware.tv.cec-service.rc
new file mode 100644
index 0000000..c79520c
--- /dev/null
+++ b/tv/cec/aidl/default/android.hardware.tv.cec-service.rc
@@ -0,0 +1,5 @@
+service vendor.cec-default /vendor/bin/hw/android.hardware.tv.cec-service
+    interface aidl android.hardware.tv.cec.IHdmiCec/default
+    class hal
+    user system
+    group system
diff --git a/tv/cec/aidl/default/android.hardware.tv.cec-service.xml b/tv/cec/aidl/default/android.hardware.tv.cec-service.xml
new file mode 100644
index 0000000..e68450d
--- /dev/null
+++ b/tv/cec/aidl/default/android.hardware.tv.cec-service.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.tv.cec</name>
+        <version>1</version>
+        <interface>
+            <name>IHdmiCec</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/tv/cec/aidl/default/fuzzer.cpp b/tv/cec/aidl/default/fuzzer.cpp
new file mode 100644
index 0000000..9f6a9ac
--- /dev/null
+++ b/tv/cec/aidl/default/fuzzer.cpp
@@ -0,0 +1,30 @@
+/*
+ * 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 <HdmiCecMock.h>
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using android::fuzzService;
+using android::hardware::tv::cec::implementation::HdmiCecMock;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    auto hdmiCecAidl = SharedRefBase::make<HdmiCecMock>();
+
+    fuzzService(hdmiCecAidl->asBinder().get(), FuzzedDataProvider(data, size));
+
+    return 0;
+}
diff --git a/tv/cec/aidl/default/serviceMock.cpp b/tv/cec/aidl/default/serviceMock.cpp
new file mode 100644
index 0000000..ab86c3f
--- /dev/null
+++ b/tv/cec/aidl/default/serviceMock.cpp
@@ -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.
+ */
+
+#define LOG_TAG "android.hardware.tv.cec-service-shim"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <hidl/HidlTransportSupport.h>
+#include <utils/Log.h>
+#include "HdmiCecMock.h"
+
+using android::hardware::tv::cec::implementation::HdmiCecMock;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+
+    std::shared_ptr<HdmiCecMock> hdmiCecAidl = ndk::SharedRefBase::make<HdmiCecMock>();
+    const std::string instance = std::string() + HdmiCecMock::descriptor + "/default";
+    binder_status_t status =
+            AServiceManager_addService(hdmiCecAidl->asBinder().get(), instance.c_str());
+    CHECK_EQ(status, STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return 0;
+}
diff --git a/tv/cec/aidl/vts/functional/Android.bp b/tv/cec/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..37fbaf0
--- /dev/null
+++ b/tv/cec/aidl/vts/functional/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsHalTvCecAidlTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalTvCecAidlTargetTest.cpp"],
+    static_libs: [
+        "android.hardware.tv.cec-V1-ndk",
+        "android.hardware.tv.hdmi-V1-ndk",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+    disable_framework: true,
+}
diff --git a/tv/cec/aidl/vts/functional/VtsHalTvCecAidlTargetTest.cpp b/tv/cec/aidl/vts/functional/VtsHalTvCecAidlTargetTest.cpp
new file mode 100644
index 0000000..69c209f
--- /dev/null
+++ b/tv/cec/aidl/vts/functional/VtsHalTvCecAidlTargetTest.cpp
@@ -0,0 +1,170 @@
+/*
+ * 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 "HdmiCec_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/tv/cec/BnHdmiCec.h>
+#include <aidl/android/hardware/tv/cec/BnHdmiCecCallback.h>
+#include <aidl/android/hardware/tv/cec/CecDeviceType.h>
+#include <aidl/android/hardware/tv/hdmi/BnHdmi.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <sstream>
+#include <vector>
+
+using ::aidl::android::hardware::tv::cec::BnHdmiCecCallback;
+using ::aidl::android::hardware::tv::cec::CecDeviceType;
+using ::aidl::android::hardware::tv::cec::CecLogicalAddress;
+using ::aidl::android::hardware::tv::cec::CecMessage;
+using ::aidl::android::hardware::tv::cec::IHdmiCec;
+using ::aidl::android::hardware::tv::cec::IHdmiCecCallback;
+using ::aidl::android::hardware::tv::cec::Result;
+using ::aidl::android::hardware::tv::cec::SendMessageResult;
+using ::aidl::android::hardware::tv::hdmi::HdmiPortInfo;
+using ::ndk::SpAIBinder;
+
+#define CEC_VERSION 0x05
+#define INCORRECT_VENDOR_ID 0x00
+#define TV_PHYSICAL_ADDRESS 0x0000
+
+// The main test class for TV CEC HAL.
+class HdmiCecTest : public ::testing::TestWithParam<std::string> {
+    static void serviceDied(void* /* cookie */) { ALOGE("VtsHalTvCecAidlTargetTest died"); }
+
+  public:
+    void SetUp() override {
+        hdmiCec = IHdmiCec::fromBinder(
+                SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+        ASSERT_NE(hdmiCec, nullptr);
+        ALOGI("%s: getService() for hdmiCec is %s", __func__,
+              hdmiCec->isRemote() ? "remote" : "local");
+
+        hdmiCecCallback = ::ndk::SharedRefBase::make<CecCallback>();
+        ASSERT_NE(hdmiCecCallback, nullptr);
+        hdmiCecDeathRecipient =
+                ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(&serviceDied));
+        ASSERT_EQ(AIBinder_linkToDeath(hdmiCec->asBinder().get(), hdmiCecDeathRecipient.get(), 0),
+                  STATUS_OK);
+    }
+
+    std::vector<int> getDeviceTypes() {
+        std::vector<int> deviceTypes;
+        FILE* p = popen("getprop ro.hdmi.device_type", "re");
+        if (p) {
+            char* line = NULL;
+            size_t len = 0;
+            if (getline(&line, &len, p) > 0) {
+                std::istringstream stream(line);
+                std::string number{};
+                while (std::getline(stream, number, ',')) {
+                    deviceTypes.push_back(stoi(number));
+                }
+            }
+            pclose(p);
+        }
+        return deviceTypes;
+    }
+
+    bool hasDeviceType(CecDeviceType type) {
+        std::vector<int> deviceTypes = getDeviceTypes();
+        return std::find(deviceTypes.begin(), deviceTypes.end(), (int)type) != deviceTypes.end();
+    }
+
+    class CecCallback : public BnHdmiCecCallback {
+      public:
+        ::ndk::ScopedAStatus onCecMessage(const CecMessage& message __unused) {
+            return ::ndk::ScopedAStatus::ok();
+        };
+    };
+
+    std::shared_ptr<IHdmiCec> hdmiCec;
+    std::shared_ptr<IHdmiCecCallback> hdmiCecCallback;
+    ::ndk::ScopedAIBinder_DeathRecipient hdmiCecDeathRecipient;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HdmiCecTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, HdmiCecTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IHdmiCec::descriptor)),
+                         android::PrintInstanceNameToString);
+
+TEST_P(HdmiCecTest, ClearAddLogicalAddress) {
+    Result addLaResult;
+    ASSERT_TRUE(hdmiCec->clearLogicalAddress().isOk());
+    ASSERT_TRUE(hdmiCec->addLogicalAddress(CecLogicalAddress::PLAYBACK_3, &addLaResult).isOk());
+    EXPECT_EQ(addLaResult, Result::SUCCESS);
+}
+
+TEST_P(HdmiCecTest, PhysicalAddress) {
+    int32_t addr;
+    ASSERT_TRUE(hdmiCec->getPhysicalAddress(&addr).isOk());
+    if (!hasDeviceType(CecDeviceType::TV)) {
+        EXPECT_NE(addr, TV_PHYSICAL_ADDRESS);
+    }
+}
+
+TEST_P(HdmiCecTest, SendMessage) {
+    CecMessage message;
+    message.initiator = CecLogicalAddress::PLAYBACK_1;
+    message.destination = CecLogicalAddress::BROADCAST;
+    message.body.resize(1);
+    message.body[0] = 131;
+    SendMessageResult result;
+    ASSERT_TRUE(hdmiCec->sendMessage(message, &result).isOk());
+    EXPECT_EQ(result, SendMessageResult::SUCCESS);
+}
+
+TEST_P(HdmiCecTest, CecVersion) {
+    int32_t version;
+    ASSERT_TRUE(hdmiCec->getCecVersion(&version).isOk());
+    EXPECT_GE(version, CEC_VERSION);
+}
+
+TEST_P(HdmiCecTest, SetCallback) {
+    ASSERT_TRUE(hdmiCec->setCallback(::ndk::SharedRefBase::make<CecCallback>()).isOk());
+}
+
+TEST_P(HdmiCecTest, VendorId) {
+    int32_t vendorId;
+    ASSERT_TRUE(hdmiCec->getVendorId(&vendorId).isOk());
+    EXPECT_NE(vendorId, INCORRECT_VENDOR_ID);
+}
+
+TEST_P(HdmiCecTest, EnableWakeupByOtp) {
+    ASSERT_TRUE(hdmiCec->enableWakeupByOtp(false).isOk());
+    // Restore option to its default value
+    ASSERT_TRUE(hdmiCec->enableWakeupByOtp(true).isOk());
+}
+
+TEST_P(HdmiCecTest, EnableCec) {
+    ASSERT_TRUE(hdmiCec->enableCec(false).isOk());
+    // Restore option to its default value
+    ASSERT_TRUE(hdmiCec->enableCec(true).isOk());
+}
+
+TEST_P(HdmiCecTest, EnableSystemCecControl) {
+    ASSERT_TRUE(hdmiCec->enableSystemCecControl(true).isOk());
+    // Restore option to its default value
+    ASSERT_TRUE(hdmiCec->enableSystemCecControl(false).isOk());
+}
+
+TEST_P(HdmiCecTest, SetLanguage) {
+    ASSERT_TRUE(hdmiCec->setLanguage("eng").isOk());
+}
diff --git a/tv/hdmi/aidl/Android.bp b/tv/hdmi/aidl/Android.bp
new file mode 100644
index 0000000..d8c6e5f
--- /dev/null
+++ b/tv/hdmi/aidl/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.tv.hdmi",
+    vendor_available: true,
+    srcs: ["android/hardware/tv/hdmi/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            sdk_version: "module_current",
+        },
+    },
+}
diff --git a/tv/hdmi/aidl/OWNERS b/tv/hdmi/aidl/OWNERS
new file mode 100644
index 0000000..d9c6783
--- /dev/null
+++ b/tv/hdmi/aidl/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 826094
+include platform/frameworks/base:/core/java/android/hardware/hdmi/OWNERS
\ No newline at end of file
diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortInfo.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortInfo.aidl
new file mode 100644
index 0000000..a5e3a2a
--- /dev/null
+++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortInfo.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.hdmi;
+@VintfStability
+parcelable HdmiPortInfo {
+  android.hardware.tv.hdmi.HdmiPortType type;
+  int portId;
+  boolean cecSupported;
+  boolean arcSupported;
+  int physicalAddress;
+}
diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortType.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortType.aidl
new file mode 100644
index 0000000..af5f0f7
--- /dev/null
+++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortType.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.hdmi;
+@Backing(type="byte") @VintfStability
+enum HdmiPortType {
+  INPUT = 0,
+  OUTPUT = 1,
+}
diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmi.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmi.aidl
new file mode 100644
index 0000000..3fc7f41
--- /dev/null
+++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmi.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.hdmi;
+@VintfStability
+interface IHdmi {
+  android.hardware.tv.hdmi.HdmiPortInfo[] getPortInfo();
+  boolean isConnected(in int portId);
+  void setCallback(in android.hardware.tv.hdmi.IHdmiCallback callback);
+}
diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmiCallback.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmiCallback.aidl
new file mode 100644
index 0000000..05fe623
--- /dev/null
+++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmiCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tv.hdmi;
+@VintfStability
+interface IHdmiCallback {
+  oneway void onHotplugEvent(in boolean connected, in int portId);
+}
diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortInfo.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortInfo.aidl
new file mode 100644
index 0000000..1d6f27d
--- /dev/null
+++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortInfo.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.tv.hdmi;
+
+import android.hardware.tv.hdmi.HdmiPortType;
+
+/**
+ * HDMI port descriptor
+ */
+@VintfStability
+parcelable HdmiPortInfo {
+    HdmiPortType type;
+    int portId; // Should start from 1 which corresponds to HDMI "port 1".
+    boolean cecSupported;
+    boolean arcSupported;
+    // The physical address of the device connected to this port, valid range is 0x0000 to 0xFFFF
+    // (ref Sec 8.7.2 of HDMI 1.4b).
+    int physicalAddress;
+}
diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortType.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortType.aidl
new file mode 100644
index 0000000..59c0d42
--- /dev/null
+++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortType.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.tv.hdmi;
+
+/**
+ * HDMI port type.
+ */
+@VintfStability
+@Backing(type="byte")
+enum HdmiPortType {
+    INPUT = 0,
+    OUTPUT = 1,
+}
diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl
new file mode 100644
index 0000000..5536846
--- /dev/null
+++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl
@@ -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 android.hardware.tv.hdmi;
+
+import android.hardware.tv.hdmi.HdmiPortInfo;
+import android.hardware.tv.hdmi.IHdmiCallback;
+
+/**
+ * HDMI HAL interface definition.
+ */
+@VintfStability
+interface IHdmi {
+    /**
+     * Gets the hdmi port information of underlying hardware.
+     *
+     * @return The list of HDMI port information
+     */
+    HdmiPortInfo[] getPortInfo();
+
+    /**
+     * Gets the connection status of the specified port.
+     *
+     * @param portId Port id to be inspected for the connection status.
+     * @return True if a device is connected, otherwise false. The HAL
+     *         must watch for +5V power signal to determine the status.
+     */
+    boolean isConnected(in int portId);
+
+    /**
+     * Sets a callback that HDMI HAL must later use for internal HDMI events
+     *
+     * @param callback Callback object to pass hdmi events to the system. The
+     *        previously registered callback must be replaced with this one.
+     *        setCallback(null) should deregister the callback.
+     */
+    void setCallback(in IHdmiCallback callback);
+}
diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmiCallback.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmiCallback.aidl
new file mode 100644
index 0000000..51275b0
--- /dev/null
+++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmiCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.tv.hdmi;
+
+/**
+ * Callbacks from the HDMI HAL implementation to notify the system of new events.
+ */
+@VintfStability
+oneway interface IHdmiCallback {
+    /**
+     * The callback function that must be called by HAL implementation to notify
+     * the system of new hotplug event.
+     */
+    void onHotplugEvent(in boolean connected, in int portId);
+}
diff --git a/tv/hdmi/aidl/default/Android.bp b/tv/hdmi/aidl/default/Android.bp
new file mode 100644
index 0000000..3e466a0
--- /dev/null
+++ b/tv/hdmi/aidl/default/Android.bp
@@ -0,0 +1,58 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_binary {
+    name: "android.hardware.tv.hdmi-service",
+    vintf_fragments: ["android.hardware.tv.hdmi-service.xml"],
+    relative_install_path: "hw",
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+    ],
+    init_rc: ["android.hardware.tv.hdmi-service.rc"],
+    srcs: [
+        "serviceMock.cpp",
+        "HdmiMock.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "liblog",
+        "libbase",
+        "libutils",
+        "libhardware",
+        "libhidlbase",
+        "android.hardware.tv.hdmi-V1-ndk",
+    ],
+}
+
+cc_fuzz {
+    name: "android.hardware.tv.hdmi-service_fuzzer",
+    defaults: ["service_fuzzer_defaults"],
+    static_libs: [
+        "android.hardware.tv.hdmi-V1-ndk",
+        "liblog",
+    ],
+    srcs: [
+        "fuzzer.cpp",
+        "HdmiMock.cpp",
+    ],
+    fuzz_config: {
+        componentid: 826094,
+    },
+}
diff --git a/tv/hdmi/aidl/default/HdmiMock.cpp b/tv/hdmi/aidl/default/HdmiMock.cpp
new file mode 100644
index 0000000..0cf5118
--- /dev/null
+++ b/tv/hdmi/aidl/default/HdmiMock.cpp
@@ -0,0 +1,178 @@
+/*
+ * 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 "android.hardware.tv.hdmi"
+#include <android-base/logging.h>
+#include <fcntl.h>
+#include <utils/Log.h>
+
+#include "HdmiMock.h"
+
+using ndk::ScopedAStatus;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace hdmi {
+namespace implementation {
+
+void HdmiMock::serviceDied(void* cookie) {
+    ALOGE("HdmiMock died");
+    auto hdmi = static_cast<HdmiMock*>(cookie);
+    hdmi->mHdmiThreadRun = false;
+}
+
+ScopedAStatus HdmiMock::getPortInfo(std::vector<HdmiPortInfo>* _aidl_return) {
+    *_aidl_return = mPortInfos;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiMock::isConnected(int32_t portId, bool* _aidl_return) {
+    // Maintain port connection status and update on hotplug event
+    if (portId <= mTotalPorts && portId >= 1) {
+        *_aidl_return = mPortConnectionStatus[portId];
+    } else {
+        *_aidl_return = false;
+    }
+
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiMock::setCallback(const std::shared_ptr<IHdmiCallback>& callback) {
+    if (mCallback != nullptr) {
+        mCallback = nullptr;
+    }
+
+    if (callback != nullptr) {
+        mCallback = callback;
+        AIBinder_linkToDeath(this->asBinder().get(), mDeathRecipient.get(), 0 /* cookie */);
+
+        mInputFile = open(HDMI_MSG_IN_FIFO, O_RDWR | O_CLOEXEC);
+        pthread_create(&mThreadId, NULL, __threadLoop, this);
+        pthread_setname_np(mThreadId, "hdmi_loop");
+    }
+    return ScopedAStatus::ok();
+}
+
+void* HdmiMock::__threadLoop(void* user) {
+    HdmiMock* const self = static_cast<HdmiMock*>(user);
+    self->threadLoop();
+    return 0;
+}
+
+int HdmiMock::readMessageFromFifo(unsigned char* buf, int msgCount) {
+    if (msgCount <= 0 || !buf) {
+        return 0;
+    }
+
+    int ret = -1;
+    // Maybe blocked at driver
+    ret = read(mInputFile, buf, msgCount);
+    if (ret < 0) {
+        ALOGE("[halimp_aidl] read :%s failed, ret:%d\n", HDMI_MSG_IN_FIFO, ret);
+        return -1;
+    }
+
+    return ret;
+}
+
+void HdmiMock::printEventBuf(const char* msg_buf, int len) {
+    int i, size = 0;
+    const int bufSize = MESSAGE_BODY_MAX_LENGTH * 3;
+    // Use 2 characters for each byte in the message plus 1 space
+    char buf[bufSize] = {0};
+
+    // Messages longer than max length will be truncated.
+    for (i = 0; i < len && size < bufSize; i++) {
+        size += sprintf(buf + size, " %02x", msg_buf[i]);
+    }
+    ALOGD("[halimp_aidl] %s, msg:%.*s", __FUNCTION__, size, buf);
+}
+
+void HdmiMock::handleHotplugMessage(unsigned char* msgBuf) {
+    bool connected = ((msgBuf[3]) & 0xf) > 0;
+    int32_t portId = static_cast<uint32_t>(msgBuf[0] & 0xf);
+
+    if (portId > static_cast<int32_t>(mPortInfos.size())) {
+        ALOGD("[halimp_aidl] ignore hot plug message, id %x does not exist", portId);
+        return;
+    }
+
+    ALOGD("[halimp_aidl] hot plug port id %x, is connected %x", (msgBuf[0] & 0xf),
+          (msgBuf[3] & 0xf));
+    mPortConnectionStatus[portId] = connected;
+    if (mPortInfos[portId].type == HdmiPortType::OUTPUT) {
+        mPhysicalAddress = (connected ? 0xffff : ((msgBuf[1] << 8) | (msgBuf[2])));
+        mPortInfos[portId].physicalAddress = mPhysicalAddress;
+        ALOGD("[halimp_aidl] hot plug physical address %x", mPhysicalAddress);
+    }
+
+    if (mCallback != nullptr) {
+        mCallback->onHotplugEvent(connected, portId);
+    }
+}
+
+void HdmiMock::threadLoop() {
+    ALOGD("[halimp_aidl] threadLoop start.");
+    unsigned char msgBuf[MESSAGE_BODY_MAX_LENGTH];
+    int r = -1;
+
+    // Open the input pipe
+    while (mInputFile < 0) {
+        usleep(1000 * 1000);
+        mInputFile = open(HDMI_MSG_IN_FIFO, O_RDONLY | O_CLOEXEC);
+    }
+    ALOGD("[halimp_aidl] file open ok, fd = %d.", mInputFile);
+
+    while (mHdmiThreadRun) {
+        memset(msgBuf, 0, sizeof(msgBuf));
+        // Try to get a message from dev.
+        // echo -n -e '\x04\x83' >> /dev/cec
+        r = readMessageFromFifo(msgBuf, MESSAGE_BODY_MAX_LENGTH);
+        if (r <= 1) {
+            // Ignore received ping messages
+            continue;
+        }
+
+        printEventBuf((const char*)msgBuf, r);
+
+        if (((msgBuf[0] >> 4) & 0xf) == 0xf) {
+            handleHotplugMessage(msgBuf);
+        }
+    }
+
+    ALOGD("[halimp_aidl] thread end.");
+}
+
+HdmiMock::HdmiMock() {
+    ALOGE("[halimp_aidl] Opening a virtual HDMI HAL for testing and virtual machine.");
+    mCallback = nullptr;
+    mPortInfos.resize(mTotalPorts);
+    mPortConnectionStatus.resize(mTotalPorts);
+    mPortInfos[0] = {.type = HdmiPortType::OUTPUT,
+                     .portId = static_cast<uint32_t>(1),
+                     .cecSupported = true,
+                     .arcSupported = false,
+                     .physicalAddress = mPhysicalAddress};
+    mPortConnectionStatus[0] = false;
+    mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(serviceDied));
+}
+
+}  // namespace implementation
+}  // namespace hdmi
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/hdmi/aidl/default/HdmiMock.h b/tv/hdmi/aidl/default/HdmiMock.h
new file mode 100644
index 0000000..05795dd
--- /dev/null
+++ b/tv/hdmi/aidl/default/HdmiMock.h
@@ -0,0 +1,77 @@
+/*
+ * 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/android/hardware/tv/hdmi/BnHdmi.h>
+#include <algorithm>
+#include <vector>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace hdmi {
+namespace implementation {
+
+using ::aidl::android::hardware::tv::hdmi::BnHdmi;
+using ::aidl::android::hardware::tv::hdmi::HdmiPortInfo;
+using ::aidl::android::hardware::tv::hdmi::HdmiPortType;
+using ::aidl::android::hardware::tv::hdmi::IHdmi;
+using ::aidl::android::hardware::tv::hdmi::IHdmiCallback;
+
+#define HDMI_MSG_IN_FIFO "/dev/hdmi_in_pipe"
+#define MESSAGE_BODY_MAX_LENGTH 4
+
+struct HdmiMock : public BnHdmi {
+    HdmiMock();
+
+    ::ndk::ScopedAStatus getPortInfo(std::vector<HdmiPortInfo>* _aidl_return) override;
+    ::ndk::ScopedAStatus isConnected(int32_t portId, bool* _aidl_return) override;
+    ::ndk::ScopedAStatus setCallback(const std::shared_ptr<IHdmiCallback>& callback) override;
+
+    void printEventBuf(const char* msg_buf, int len);
+
+  private:
+    static void* __threadLoop(void* data);
+    void threadLoop();
+    int readMessageFromFifo(unsigned char* buf, int msgCount);
+    void handleHotplugMessage(unsigned char* msgBuf);
+
+  private:
+    static void serviceDied(void* cookie);
+    std::shared_ptr<IHdmiCallback> mCallback;
+
+    // Variables for the virtual HDMI hal impl
+    std::vector<HdmiPortInfo> mPortInfos;
+    std::vector<bool> mPortConnectionStatus;
+
+    // Port configuration
+    uint16_t mPhysicalAddress = 0xFFFF;
+    int mTotalPorts = 1;
+
+    // Testing variables
+    // Input file descriptor
+    int mInputFile;
+    bool mHdmiThreadRun = true;
+    pthread_t mThreadId = 0;
+
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+};
+}  // namespace implementation
+}  // namespace hdmi
+}  // Namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.rc b/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.rc
new file mode 100644
index 0000000..c926221
--- /dev/null
+++ b/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.rc
@@ -0,0 +1,5 @@
+service vendor.hdmi-default /vendor/bin/hw/android.hardware.tv.hdmi-service
+    interface aidl android.hardware.tv.hdmi.IHdmi/default
+    class hal
+    user system
+    group system
diff --git a/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.xml b/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.xml
new file mode 100644
index 0000000..a03c199
--- /dev/null
+++ b/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.tv.hdmi</name>
+        <version>1</version>
+        <interface>
+            <name>IHdmi</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/tv/hdmi/aidl/default/fuzzer.cpp b/tv/hdmi/aidl/default/fuzzer.cpp
new file mode 100644
index 0000000..06a2bc0
--- /dev/null
+++ b/tv/hdmi/aidl/default/fuzzer.cpp
@@ -0,0 +1,30 @@
+/*
+ * 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 <HdmiMock.h>
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using android::fuzzService;
+using android::hardware::tv::hdmi::implementation::HdmiMock;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    auto hdmiAidl = SharedRefBase::make<HdmiMock>();
+
+    fuzzService(hdmiAidl->asBinder().get(), FuzzedDataProvider(data, size));
+
+    return 0;
+}
diff --git a/tv/hdmi/aidl/default/serviceMock.cpp b/tv/hdmi/aidl/default/serviceMock.cpp
new file mode 100644
index 0000000..1d8bf51
--- /dev/null
+++ b/tv/hdmi/aidl/default/serviceMock.cpp
@@ -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.
+ */
+
+#define LOG_TAG "android.hardware.tv.hdmi-service-shim"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <hidl/HidlTransportSupport.h>
+#include <utils/Log.h>
+#include "HdmiMock.h"
+
+using android::hardware::tv::hdmi::implementation::HdmiMock;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+
+    std::shared_ptr<HdmiMock> hdmiAidl = ndk::SharedRefBase::make<HdmiMock>();
+    const std::string instance = std::string() + HdmiMock::descriptor + "/default";
+    binder_status_t status =
+            AServiceManager_addService(hdmiAidl->asBinder().get(), instance.c_str());
+    CHECK_EQ(status, STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return 0;
+}
diff --git a/tv/hdmi/aidl/vts/functional/Android.bp b/tv/hdmi/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..f9af58d
--- /dev/null
+++ b/tv/hdmi/aidl/vts/functional/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 {
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsHalTvHdmiAidlTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalTvHdmiAidlTargetTest.cpp"],
+    static_libs: [
+        "android.hardware.tv.hdmi-V1-ndk",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+    disable_framework: true,
+}
diff --git a/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp b/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp
new file mode 100644
index 0000000..78c2590
--- /dev/null
+++ b/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp
@@ -0,0 +1,103 @@
+/*
+ * 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 "Hdmi_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/tv/hdmi/BnHdmi.h>
+#include <aidl/android/hardware/tv/hdmi/BnHdmiCallback.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <sstream>
+#include <vector>
+
+using ::aidl::android::hardware::tv::hdmi::BnHdmiCallback;
+using ::aidl::android::hardware::tv::hdmi::HdmiPortInfo;
+using ::aidl::android::hardware::tv::hdmi::HdmiPortType;
+using ::aidl::android::hardware::tv::hdmi::IHdmi;
+using ::aidl::android::hardware::tv::hdmi::IHdmiCallback;
+using ::ndk::SpAIBinder;
+
+#define INCORRECT_VENDOR_ID 0x00
+#define TV_PHYSICAL_ADDRESS 0x0000
+
+// The main test class for TV HDMI HAL.
+class HdmiTest : public ::testing::TestWithParam<std::string> {
+    static void serviceDied(void* /* cookie */) { ALOGE("VtsHalTvCecAidlTargetTest died"); }
+
+  public:
+    void SetUp() override {
+        hdmi = IHdmi::fromBinder(SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+        ASSERT_NE(hdmi, nullptr);
+        ALOGI("%s: getService() for hdmi is %s", __func__, hdmi->isRemote() ? "remote" : "local");
+
+        hdmiCallback = ::ndk::SharedRefBase::make<HdmiCallback>();
+        ASSERT_NE(hdmiCallback, nullptr);
+        hdmiDeathRecipient =
+                ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(&serviceDied));
+        ASSERT_EQ(AIBinder_linkToDeath(hdmi->asBinder().get(), hdmiDeathRecipient.get(), 0),
+                  STATUS_OK);
+    }
+
+    class HdmiCallback : public BnHdmiCallback {
+      public:
+        ::ndk::ScopedAStatus onHotplugEvent(bool connected __unused, int32_t portId __unused) {
+            return ::ndk::ScopedAStatus::ok();
+        };
+    };
+
+    std::shared_ptr<IHdmi> hdmi;
+    std::shared_ptr<IHdmiCallback> hdmiCallback;
+    ::ndk::ScopedAIBinder_DeathRecipient hdmiDeathRecipient;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HdmiTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, HdmiTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IHdmi::descriptor)),
+                         android::PrintInstanceNameToString);
+
+TEST_P(HdmiTest, SetCallback) {
+    ASSERT_TRUE(hdmi->setCallback(::ndk::SharedRefBase::make<HdmiCallback>()).isOk());
+}
+
+TEST_P(HdmiTest, GetPortInfo) {
+    std::vector<HdmiPortInfo> ports;
+    ASSERT_TRUE(hdmi->getPortInfo(&ports).isOk());
+
+    bool cecSupportedOnDevice = false;
+    for (size_t i = 0; i < ports.size(); ++i) {
+        EXPECT_TRUE((ports[i].type == HdmiPortType::OUTPUT) ||
+                    (ports[i].type == HdmiPortType::INPUT));
+        if (ports[i].portId == 0) {
+            ALOGW("%s: Port id should start from 1", __func__);
+        }
+        cecSupportedOnDevice = cecSupportedOnDevice | ports[i].cecSupported;
+    }
+    EXPECT_NE(cecSupportedOnDevice, false) << "At least one port should support CEC";
+}
+
+TEST_P(HdmiTest, IsConnected) {
+    std::vector<HdmiPortInfo> ports;
+    ASSERT_TRUE(hdmi->getPortInfo(&ports).isOk());
+    for (size_t i = 0; i < ports.size(); ++i) {
+        bool connected;
+        ASSERT_TRUE(hdmi->isConnected(ports[i].portId, &connected).isOk());
+    }
+}
diff --git a/tv/input/OWNERS b/tv/input/OWNERS
new file mode 100644
index 0000000..a02291a
--- /dev/null
+++ b/tv/input/OWNERS
@@ -0,0 +1,4 @@
+hgchen@google.com
+shubang@google.com
+quxiangfang@google.com
+yixiaoluo@google.com
diff --git a/usb/1.0/default/Usb.cpp b/usb/1.0/default/Usb.cpp
index 6eb8842..573e0e3 100644
--- a/usb/1.0/default/Usb.cpp
+++ b/usb/1.0/default/Usb.cpp
@@ -234,7 +234,7 @@
     else
         return Status::UNRECOGNIZED_ROLE;
 
-        return Status::SUCCESS;
+    return Status::SUCCESS;
 }
 
 Status getPortStatusHelper (hidl_vec<PortStatus>& currentPortStatus) {
diff --git a/usb/aidl/Android.bp b/usb/aidl/Android.bp
index 7eb6020..4f59f02 100644
--- a/usb/aidl/Android.bp
+++ b/usb/aidl/Android.bp
@@ -33,11 +33,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions_with_info: [
         {
diff --git a/uwb/aidl/Android.bp b/uwb/aidl/Android.bp
index cc61046..52f0605 100755
--- a/uwb/aidl/Android.bp
+++ b/uwb/aidl/Android.bp
@@ -21,9 +21,6 @@
             enabled: false,
         },
         ndk: {
-            vndk: {
-                enabled: true,
-            },
             apex_available: [
                 "//apex_available:platform",
                 "com.android.uwb",
diff --git a/vibrator/aidl/Android.bp b/vibrator/aidl/Android.bp
index d4d5857..86ef027 100644
--- a/vibrator/aidl/Android.bp
+++ b/vibrator/aidl/Android.bp
@@ -19,11 +19,6 @@
         java: {
             sdk_version: "module_current",
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions: [
         "1",
diff --git a/vibrator/aidl/default/Android.bp b/vibrator/aidl/default/Android.bp
index c4140be..78bb4ed 100644
--- a/vibrator/aidl/default/Android.bp
+++ b/vibrator/aidl/default/Android.bp
@@ -57,33 +57,12 @@
 cc_fuzz {
     name: "android.hardware.vibrator-service.example_fuzzer",
     host_supported: true,
+    defaults: ["service_fuzzer_defaults"],
     static_libs: [
         "android.hardware.vibrator-V2-ndk",
-        "libbase",
-        "libbinder_random_parcel",
-        "libcutils",
         "liblog",
         "libvibratorexampleimpl",
     ],
-    target: {
-        android: {
-            shared_libs: [
-                "libbinder_ndk",
-                "libbinder",
-                "libutils",
-            ],
-        },
-        host: {
-            static_libs: [
-                "libbinder_ndk",
-                "libbinder",
-                "libutils",
-            ],
-        },
-        darwin: {
-            enabled: false,
-        },
-    },
     srcs: ["fuzzer.cpp"],
     fuzz_config: {
         cc: [
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 3841715..f50a5e7 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -332,6 +332,7 @@
         sleep(1);
         EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(1.0f).exceptionCode());
         sleep(1);
+        EXPECT_TRUE(vibrator->off().isOk());
     }
 }
 
@@ -443,7 +444,7 @@
 
             effect.delayMs = std::rand() % (maxDelay + 1);
             effect.primitive = primitive;
-            effect.scale = static_cast<float>(std::rand()) / RAND_MAX;
+            effect.scale = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
             composite.emplace_back(effect);
 
             if (composite.size() == maxSize) {
diff --git a/weaver/aidl/Android.bp b/weaver/aidl/Android.bp
index 8b4306f..caa92aa 100644
--- a/weaver/aidl/Android.bp
+++ b/weaver/aidl/Android.bp
@@ -16,11 +16,6 @@
         java: {
             platform_apis: true,
         },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
     },
     versions: ["1"],
 }
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
index e6e61cf..02f8209 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -66,7 +66,7 @@
 bool configureChipToSupportIfaceTypeInternal(const sp<IWifiChip>& wifi_chip,
                                              IfaceType type,
                                              ChipModeId* configured_mode_id) {
-    if (!configured_mode_id) {
+    if (!configured_mode_id || !wifi_chip.get()) {
         return false;
     }
     const auto& status_and_modes = HIDL_INVOKE(wifi_chip, getAvailableModes);
diff --git a/wifi/1.4/vts/functional/wifi_hidl_test_utils_1_4.h b/wifi/1.4/vts/functional/wifi_hidl_test_utils_1_4.h
index a2c5815..ca7b57a 100644
--- a/wifi/1.4/vts/functional/wifi_hidl_test_utils_1_4.h
+++ b/wifi/1.4/vts/functional/wifi_hidl_test_utils_1_4.h
@@ -28,6 +28,6 @@
 // These helper functions should be modified to return vectors if we support
 // multiple instances.
 android::sp<android::hardware::wifi::V1_4::IWifiChip> getWifiChip_1_4(
-        const std::string& instance_name);
+    const std::string& instance_name);
 android::sp<android::hardware::wifi::V1_4::IWifiApIface> getWifiApIface_1_4(
-        const std::string& instance_name);
+    const std::string& instance_name);
diff --git a/wifi/1.6/default/Android.bp b/wifi/1.6/default/Android.bp
index d48d183..0f98e71 100644
--- a/wifi/1.6/default/Android.bp
+++ b/wifi/1.6/default/Android.bp
@@ -16,42 +16,61 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-filegroup {
-    name: "android.hardware.wifi@1.0-service_srcs",
-    srcs: ["service.cpp"],
+soong_config_module_type {
+    name: "wifi_hal_cc_defaults",
+    module_type: "cc_defaults",
+    config_namespace: "wifi",
+    bool_variables: [
+        "hidl_feature_aware", // WIFI_HIDL_FEATURE_AWARE
+        "hidl_feature_dual_interface", // WIFI_HIDL_FEATURE_DUAL_INTERFACE
+        "hidl_feature_disable_ap", // WIFI_HIDL_FEATURE_DISABLE_AP
+        "hidl_feature_disable_ap_mac_randomization", // WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
+        "avoid_iface_reset_mac_change", // WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+    ],
+    value_variables: [
+        "hal_interface_combinations", // WIFI_HAL_INTERFACE_COMBINATIONS
+    ],
+    properties: [
+        "cppflags",
+    ],
 }
 
-cc_defaults {
-    name: "android.hardware.wifi@1.0-service_default",
-    srcs: [":android.hardware.wifi@1.0-service_srcs"],
-    relative_install_path: "hw",
-    soc_specific: true,
-    shared_libs: [
-        "android.hardware.wifi@1.0",
-        "android.hardware.wifi@1.1",
-        "android.hardware.wifi@1.2",
-        "android.hardware.wifi@1.3",
-        "android.hardware.wifi@1.4",
-        "android.hardware.wifi@1.5",
-        "android.hardware.wifi@1.6",
-        "libbase",
-        "libcutils",
-        "libhidlbase",
-        "liblog",
-        "libnl",
-        "libutils",
-        "libwifi-system-iface",
-        "libxml2",
-    ],
+wifi_hal_cc_defaults {
+    name: "android.hardware.wifi@1.0-service-cppflags-defaults",
+    soong_config_variables: {
+        hidl_feature_aware: {
+            cppflags: ["-DWIFI_HIDL_FEATURE_AWARE"],
+        },
+        hidl_feature_dual_interface: {
+            cppflags: ["-DWIFI_HIDL_FEATURE_DUAL_INTERFACE"],
+        },
+        hidl_feature_disable_ap: {
+            cppflags: ["-DWIFI_HIDL_FEATURE_DISABLE_AP"],
+        },
+        hidl_feature_disable_ap_mac_randomization: {
+            cppflags: ["-DWIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION"],
+        },
+        avoid_iface_reset_mac_change: {
+            cppflags: ["-DWIFI_AVOID_IFACE_RESET_MAC_CHANGE"],
+        },
+        hal_interface_combinations: {
+            cppflags: ["-DWIFI_HAL_INTERFACE_COMBINATIONS=%s"],
+        },
+    },
+}
+
+cc_library_static {
+    name: "android.hardware.wifi@1.0-service-lib",
+    defaults: ["android.hardware.wifi@1.0-service-cppflags-defaults"],
+    proprietary: true,
+    compile_multilib: "first",
     cppflags: [
         "-Wall",
         "-Werror",
         "-Wextra",
     ],
-}
-
-filegroup {
-    name: "android.hardware.wifi@1.0-service-lib_srcs",
+    // Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed.
+    cflags: ["-Wno-error=implicit-fallthrough"],
     srcs: [
         "hidl_struct_util.cpp",
         "hidl_sync_util.cpp",
@@ -71,14 +90,17 @@
         "wifi_sta_iface.cpp",
         "wifi_status_util.cpp",
     ],
-}
 
-cc_defaults {
-    name: "android.hardware.wifi@1.0-service-lib_defaults",
-    srcs: [":android.hardware.wifi@1.0-service-lib_srcs"],
-    relative_install_path: "hw",
-    soc_specific: true,
     shared_libs: [
+        "libbase",
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libnl",
+        "libutils",
+        "libwifi-hal",
+        "libwifi-system-iface",
+        "libxml2",
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
@@ -86,22 +108,131 @@
         "android.hardware.wifi@1.4",
         "android.hardware.wifi@1.5",
         "android.hardware.wifi@1.6",
+    ],
+
+    export_include_dirs: ["."],
+}
+
+cc_binary {
+    name: "android.hardware.wifi@1.0-service",
+    vintf_fragments: ["android.hardware.wifi@1.0-service.xml"],
+    relative_install_path: "hw",
+    proprietary: true,
+    cppflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    srcs: ["service.cpp"],
+    shared_libs: [
         "libbase",
         "libcutils",
         "libhidlbase",
         "liblog",
         "libnl",
         "libutils",
+        "libwifi-hal",
         "libwifi-system-iface",
         "libxml2",
+        "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
+        "android.hardware.wifi@1.4",
+        "android.hardware.wifi@1.5",
+        "android.hardware.wifi@1.6",
     ],
-    // Generated by building android.hardware.wifi@1.0-service-lib and printing LOCAL_CPPFLAGS.
+    static_libs: ["android.hardware.wifi@1.0-service-lib"],
+    init_rc: ["android.hardware.wifi@1.0-service.rc"],
+}
+
+cc_binary {
+    name: "android.hardware.wifi@1.0-service-lazy",
+    vintf_fragments: ["android.hardware.wifi@1.0-service.xml"],
+    overrides: ["android.hardware.wifi@1.0-service"],
+    cflags: ["-DLAZY_SERVICE"],
+    relative_install_path: "hw",
+    proprietary: true,
     cppflags: [
         "-Wall",
         "-Werror",
         "-Wextra",
-        "-DWIFI_HIDL_FEATURE_DUAL_INTERFACE",
     ],
-    export_include_dirs: ["."],
-    include_dirs: ["external/libxml2/include"],
+    srcs: ["service.cpp"],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libnl",
+        "libutils",
+        "libwifi-hal",
+        "libwifi-system-iface",
+        "libxml2",
+        "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
+        "android.hardware.wifi@1.4",
+        "android.hardware.wifi@1.5",
+        "android.hardware.wifi@1.6",
+    ],
+    static_libs: ["android.hardware.wifi@1.0-service-lib"],
+    init_rc: ["android.hardware.wifi@1.0-service-lazy.rc"],
+}
+
+cc_test {
+    name: "android.hardware.wifi@1.0-service-tests",
+    proprietary: true,
+    compile_multilib: "first",
+    cppflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    srcs: [
+        "tests/hidl_struct_util_unit_tests.cpp",
+        "tests/main.cpp",
+        "tests/mock_interface_tool.cpp",
+        "tests/mock_wifi_feature_flags.cpp",
+        "tests/mock_wifi_iface_util.cpp",
+        "tests/mock_wifi_legacy_hal.cpp",
+        "tests/mock_wifi_mode_controller.cpp",
+        "tests/ringbuffer_unit_tests.cpp",
+        "tests/wifi_nan_iface_unit_tests.cpp",
+        "tests/wifi_chip_unit_tests.cpp",
+        "tests/wifi_iface_util_unit_tests.cpp",
+    ],
+    static_libs: [
+        "libgmock",
+        "libgtest",
+        "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
+        "android.hardware.wifi@1.4",
+        "android.hardware.wifi@1.5",
+        "android.hardware.wifi@1.6",
+        "android.hardware.wifi@1.0-service-lib",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libnl",
+        "libutils",
+        "libwifi-hal",
+        "libwifi-system-iface",
+    ],
+}
+
+filegroup {
+    name: "default-android.hardware.wifi@1.0-service.rc",
+    srcs: ["android.hardware.wifi@1.0-service.rc"],
+}
+
+filegroup {
+    name: "default-android.hardware.wifi@1.0-service.xml",
+    srcs: ["android.hardware.wifi@1.0-service.xml"],
 }
diff --git a/wifi/1.6/default/Android.mk b/wifi/1.6/default/Android.mk
deleted file mode 100644
index ca1c022..0000000
--- a/wifi/1.6/default/Android.mk
+++ /dev/null
@@ -1,202 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-LOCAL_PATH := $(call my-dir)
-
-###
-### android.hardware.wifi static library
-###
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.wifi@1.0-service-lib
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_CPPFLAGS := -Wall -Werror -Wextra
-ifdef WIFI_HAL_INTERFACE_COMBINATIONS
-LOCAL_CPPFLAGS += -DWIFI_HAL_INTERFACE_COMBINATIONS="$(WIFI_HAL_INTERFACE_COMBINATIONS)"
-endif
-ifdef WIFI_HIDL_FEATURE_AWARE
-LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_AWARE
-endif
-ifdef WIFI_HIDL_FEATURE_DUAL_INTERFACE
-LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DUAL_INTERFACE
-endif
-ifdef WIFI_HIDL_FEATURE_DISABLE_AP
-LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DISABLE_AP
-endif
-ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
-LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
-endif
-ifdef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
-LOCAL_CPPFLAGS += -DWIFI_AVOID_IFACE_RESET_MAC_CHANGE
-endif
-# Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed.
-LOCAL_CFLAGS += -Wno-error=implicit-fallthrough
-LOCAL_SRC_FILES := \
-    hidl_struct_util.cpp \
-    hidl_sync_util.cpp \
-    ringbuffer.cpp \
-    wifi.cpp \
-    wifi_ap_iface.cpp \
-    wifi_chip.cpp \
-    wifi_feature_flags.cpp \
-    wifi_iface_util.cpp \
-    wifi_legacy_hal.cpp \
-    wifi_legacy_hal_factory.cpp \
-    wifi_legacy_hal_stubs.cpp \
-    wifi_mode_controller.cpp \
-    wifi_nan_iface.cpp \
-    wifi_p2p_iface.cpp \
-    wifi_rtt_controller.cpp \
-    wifi_sta_iface.cpp \
-    wifi_status_util.cpp
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libcutils \
-    libhidlbase \
-    liblog \
-    libnl \
-    libutils \
-    libwifi-hal \
-    libwifi-system-iface \
-    libxml2 \
-    android.hardware.wifi@1.0 \
-    android.hardware.wifi@1.1 \
-    android.hardware.wifi@1.2 \
-    android.hardware.wifi@1.3 \
-    android.hardware.wifi@1.4 \
-    android.hardware.wifi@1.5 \
-    android.hardware.wifi@1.6
-LOCAL_C_INCLUDES += $(TOP)/external/libxml2/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-include $(BUILD_STATIC_LIBRARY)
-
-###
-### android.hardware.wifi daemon
-###
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.wifi@1.0-service
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-LOCAL_VINTF_FRAGMENTS := android.hardware.wifi@1.0-service.xml
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_CPPFLAGS := -Wall -Werror -Wextra
-LOCAL_SRC_FILES := \
-    service.cpp
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libcutils \
-    libhidlbase \
-    liblog \
-    libnl \
-    libutils \
-    libwifi-hal \
-    libwifi-system-iface \
-    libxml2 \
-    android.hardware.wifi@1.0 \
-    android.hardware.wifi@1.1 \
-    android.hardware.wifi@1.2 \
-    android.hardware.wifi@1.3 \
-    android.hardware.wifi@1.4 \
-    android.hardware.wifi@1.5 \
-    android.hardware.wifi@1.6
-LOCAL_STATIC_LIBRARIES := \
-    android.hardware.wifi@1.0-service-lib
-LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc
-include $(BUILD_EXECUTABLE)
-
-###
-### android.hardware.wifi daemon
-###
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.wifi@1.0-service-lazy
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-LOCAL_VINTF_FRAGMENTS := android.hardware.wifi@1.0-service.xml
-LOCAL_OVERRIDES_MODULES := android.hardware.wifi@1.0-service
-LOCAL_CFLAGS := -DLAZY_SERVICE
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_CPPFLAGS := -Wall -Werror -Wextra
-LOCAL_SRC_FILES := \
-    service.cpp
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libcutils \
-    libhidlbase \
-    liblog \
-    libnl \
-    libutils \
-    libwifi-hal \
-    libwifi-system-iface \
-    libxml2 \
-    android.hardware.wifi@1.0 \
-    android.hardware.wifi@1.1 \
-    android.hardware.wifi@1.2 \
-    android.hardware.wifi@1.3 \
-    android.hardware.wifi@1.4 \
-    android.hardware.wifi@1.5 \
-    android.hardware.wifi@1.6
-LOCAL_STATIC_LIBRARIES := \
-    android.hardware.wifi@1.0-service-lib
-LOCAL_INIT_RC := android.hardware.wifi@1.0-service-lazy.rc
-include $(BUILD_EXECUTABLE)
-
-###
-### android.hardware.wifi unit tests.
-###
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.wifi@1.0-service-tests
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_CPPFLAGS := -Wall -Werror -Wextra
-LOCAL_SRC_FILES := \
-    tests/hidl_struct_util_unit_tests.cpp \
-    tests/main.cpp \
-    tests/mock_interface_tool.cpp \
-    tests/mock_wifi_feature_flags.cpp \
-    tests/mock_wifi_iface_util.cpp \
-    tests/mock_wifi_legacy_hal.cpp \
-    tests/mock_wifi_mode_controller.cpp \
-    tests/ringbuffer_unit_tests.cpp \
-    tests/wifi_nan_iface_unit_tests.cpp \
-    tests/wifi_chip_unit_tests.cpp \
-    tests/wifi_iface_util_unit_tests.cpp
-LOCAL_STATIC_LIBRARIES := \
-    libgmock \
-    libgtest \
-    android.hardware.wifi@1.0 \
-    android.hardware.wifi@1.1 \
-    android.hardware.wifi@1.2 \
-    android.hardware.wifi@1.3 \
-    android.hardware.wifi@1.4 \
-    android.hardware.wifi@1.5 \
-    android.hardware.wifi@1.6 \
-    android.hardware.wifi@1.0-service-lib
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libcutils \
-    libhidlbase \
-    liblog \
-    libnl \
-    libutils \
-    libwifi-hal \
-    libwifi-system-iface
-include $(BUILD_NATIVE_TEST)
diff --git a/wifi/1.6/default/wifi_legacy_hal.cpp b/wifi/1.6/default/wifi_legacy_hal.cpp
index 2211897..c9bcdc5 100644
--- a/wifi/1.6/default/wifi_legacy_hal.cpp
+++ b/wifi/1.6/default/wifi_legacy_hal.cpp
@@ -555,7 +555,7 @@
 
     status = global_func_table_.wifi_read_packet_filter(
             getIfaceHandle(iface_name), /*src_offset=*/0, buffer.data(), buffer.size());
-    return {status, move(buffer)};
+    return {status, std::move(buffer)};
 }
 
 std::pair<wifi_error, wifi_gscan_capabilities> WifiLegacyHal::getGscanCapabilities(
diff --git a/wifi/aidl/Android.bp b/wifi/aidl/Android.bp
new file mode 100644
index 0000000..c0ca667
--- /dev/null
+++ b/wifi/aidl/Android.bp
@@ -0,0 +1,44 @@
+// 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.wifi",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/wifi/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            sdk_version: "module_current",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.wifi",
+            ],
+            min_sdk_version: "30",
+            lint: {
+                enabled: false,
+            },
+        },
+    },
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifi.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifi.aidl
new file mode 100644
index 0000000..cc995fc
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifi.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+interface IWifi {
+  @PropagateAllowBlocking android.hardware.wifi.IWifiChip getChip(int chipId);
+  int[] getChipIds();
+  boolean isStarted();
+  void registerEventCallback(in android.hardware.wifi.IWifiEventCallback callback);
+  void start();
+  void stop();
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiApIface.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiApIface.aidl
new file mode 100644
index 0000000..a102b97
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiApIface.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+interface IWifiApIface {
+  String getName();
+  String[] getBridgedInstances();
+  byte[6] getFactoryMacAddress();
+  void setCountryCode(in byte[2] code);
+  int[] getValidFrequenciesForBand(in android.hardware.wifi.WifiBand band);
+  void resetToFactoryMacAddress();
+  void setMacAddress(in byte[6] mac);
+}
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
new file mode 100644
index 0000000..647891f
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+interface IWifiChip {
+  void configureChip(in int modeId);
+  @PropagateAllowBlocking android.hardware.wifi.IWifiApIface createApIface();
+  @PropagateAllowBlocking android.hardware.wifi.IWifiApIface createBridgedApIface();
+  @PropagateAllowBlocking android.hardware.wifi.IWifiNanIface createNanIface();
+  @PropagateAllowBlocking android.hardware.wifi.IWifiP2pIface createP2pIface();
+  @PropagateAllowBlocking android.hardware.wifi.IWifiRttController createRttController(in android.hardware.wifi.IWifiStaIface boundIface);
+  @PropagateAllowBlocking android.hardware.wifi.IWifiStaIface createStaIface();
+  void enableDebugErrorAlerts(in boolean enable);
+  void flushRingBufferToFile();
+  void forceDumpToDebugRingBuffer(in String ringName);
+  @PropagateAllowBlocking android.hardware.wifi.IWifiApIface getApIface(in String ifname);
+  String[] getApIfaceNames();
+  android.hardware.wifi.IWifiChip.ChipMode[] getAvailableModes();
+  android.hardware.wifi.IWifiChip.ChipCapabilityMask getCapabilities();
+  android.hardware.wifi.WifiDebugHostWakeReasonStats getDebugHostWakeReasonStats();
+  android.hardware.wifi.WifiDebugRingBufferStatus[] getDebugRingBuffersStatus();
+  int getId();
+  int getMode();
+  @PropagateAllowBlocking android.hardware.wifi.IWifiNanIface getNanIface(in String ifname);
+  String[] getNanIfaceNames();
+  @PropagateAllowBlocking android.hardware.wifi.IWifiP2pIface getP2pIface(in String ifname);
+  String[] getP2pIfaceNames();
+  @PropagateAllowBlocking android.hardware.wifi.IWifiStaIface getStaIface(in String ifname);
+  String[] getStaIfaceNames();
+  android.hardware.wifi.WifiRadioCombinationMatrix getSupportedRadioCombinationsMatrix();
+  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);
+  void removeIfaceInstanceFromBridgedApIface(in String brIfaceName, in String ifaceInstanceName);
+  void removeNanIface(in String ifname);
+  void removeP2pIface(in String ifname);
+  void removeStaIface(in String ifname);
+  android.hardware.wifi.IWifiChip.ChipDebugInfo requestChipDebugInfo();
+  byte[] requestDriverDebugDump();
+  byte[] requestFirmwareDebugDump();
+  void resetTxPowerScenario();
+  void selectTxPowerScenario(in android.hardware.wifi.IWifiChip.TxPowerScenario scenario);
+  void setCoexUnsafeChannels(in android.hardware.wifi.IWifiChip.CoexUnsafeChannel[] unsafeChannels, in android.hardware.wifi.IWifiChip.CoexRestriction restrictions);
+  void setCountryCode(in byte[2] code);
+  void setLatencyMode(in android.hardware.wifi.IWifiChip.LatencyMode mode);
+  void setMultiStaPrimaryConnection(in String ifName);
+  void setMultiStaUseCase(in android.hardware.wifi.IWifiChip.MultiStaUseCase useCase);
+  void startLoggingToDebugRingBuffer(in String ringName, in android.hardware.wifi.WifiDebugRingBufferVerboseLevel verboseLevel, in int maxIntervalInSec, in int minDataSizeInBytes);
+  void stopLoggingToDebugRingBuffer();
+  void triggerSubsystemRestart();
+  const int NO_POWER_CAP_CONSTANT = 2147483647;
+  @Backing(type="int") @VintfStability
+  enum ChipCapabilityMask {
+    DEBUG_MEMORY_FIRMWARE_DUMP = 1,
+    DEBUG_MEMORY_DRIVER_DUMP = 2,
+    DEBUG_RING_BUFFER_CONNECT_EVENT = 4,
+    DEBUG_RING_BUFFER_POWER_EVENT = 8,
+    DEBUG_RING_BUFFER_WAKELOCK_EVENT = 16,
+    DEBUG_RING_BUFFER_VENDOR_DATA = 32,
+    DEBUG_HOST_WAKE_REASON_STATS = 64,
+    DEBUG_ERROR_ALERTS = 128,
+    SET_TX_POWER_LIMIT = 256,
+    D2D_RTT = 512,
+    D2AP_RTT = 1024,
+    USE_BODY_HEAD_SAR = 2048,
+    SET_LATENCY_MODE = 4096,
+    P2P_RAND_MAC = 8192,
+    WIGIG = 16384,
+  }
+  @VintfStability
+  parcelable ChipConcurrencyCombinationLimit {
+    android.hardware.wifi.IfaceConcurrencyType[] types;
+    int maxIfaces;
+  }
+  @VintfStability
+  parcelable ChipConcurrencyCombination {
+    android.hardware.wifi.IWifiChip.ChipConcurrencyCombinationLimit[] limits;
+  }
+  @VintfStability
+  parcelable ChipDebugInfo {
+    String driverDescription;
+    String firmwareDescription;
+  }
+  @VintfStability
+  parcelable ChipIfaceCombinationLimit {
+    android.hardware.wifi.IfaceType[] types;
+    int maxIfaces;
+  }
+  @VintfStability
+  parcelable ChipIfaceCombination {
+    android.hardware.wifi.IWifiChip.ChipIfaceCombinationLimit[] limits;
+  }
+  @VintfStability
+  parcelable ChipMode {
+    int id;
+    android.hardware.wifi.IWifiChip.ChipConcurrencyCombination[] availableCombinations;
+  }
+  @Backing(type="int") @VintfStability
+  enum CoexRestriction {
+    WIFI_DIRECT = 1,
+    SOFTAP = 2,
+    WIFI_AWARE = 4,
+  }
+  @VintfStability
+  parcelable CoexUnsafeChannel {
+    android.hardware.wifi.WifiBand band;
+    int channel;
+    int powerCapDbm;
+  }
+  @Backing(type="int") @VintfStability
+  enum LatencyMode {
+    NORMAL = 0,
+    LOW = 1,
+  }
+  @Backing(type="byte") @VintfStability
+  enum MultiStaUseCase {
+    DUAL_STA_TRANSIENT_PREFER_PRIMARY = 0,
+    DUAL_STA_NON_TRANSIENT_UNBIASED = 1,
+  }
+  @Backing(type="int") @VintfStability
+  enum TxPowerScenario {
+    VOICE_CALL = 0,
+    ON_HEAD_CELL_OFF = 1,
+    ON_HEAD_CELL_ON = 2,
+    ON_BODY_CELL_OFF = 3,
+    ON_BODY_CELL_ON = 4,
+  }
+  @Backing(type="int") @VintfStability
+  enum UsableChannelFilter {
+    CELLULAR_COEXISTENCE = 1,
+    CONCURRENCY = 2,
+    NAN_INSTANT_MODE = 4,
+  }
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChipEventCallback.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChipEventCallback.aidl
new file mode 100644
index 0000000..3fd8533
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChipEventCallback.aidl
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+interface IWifiChipEventCallback {
+  oneway void onChipReconfigureFailure(in android.hardware.wifi.WifiStatusCode status);
+  oneway void onChipReconfigured(in int modeId);
+  oneway void onDebugErrorAlert(in int errorCode, in byte[] debugData);
+  oneway void onDebugRingBufferDataAvailable(in android.hardware.wifi.WifiDebugRingBufferStatus status, in byte[] data);
+  oneway void onIfaceAdded(in android.hardware.wifi.IfaceType type, in String name);
+  oneway void onIfaceRemoved(in android.hardware.wifi.IfaceType type, in String name);
+  oneway void onRadioModeChange(in android.hardware.wifi.IWifiChipEventCallback.RadioModeInfo[] radioModeInfos);
+  @VintfStability
+  parcelable IfaceInfo {
+    String name;
+    int channel;
+  }
+  @VintfStability
+  parcelable RadioModeInfo {
+    int radioId;
+    android.hardware.wifi.WifiBand bandInfo;
+    android.hardware.wifi.IWifiChipEventCallback.IfaceInfo[] ifaceInfos;
+  }
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiEventCallback.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiEventCallback.aidl
new file mode 100644
index 0000000..00e5cb6
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiEventCallback.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+interface IWifiEventCallback {
+  oneway void onFailure(in android.hardware.wifi.WifiStatusCode status);
+  oneway void onStart();
+  oneway void onStop();
+  oneway void onSubsystemRestart(in android.hardware.wifi.WifiStatusCode status);
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIface.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIface.aidl
new file mode 100644
index 0000000..070ca24
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIface.aidl
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+interface IWifiNanIface {
+  String getName();
+  void configRequest(in char cmdId, in android.hardware.wifi.NanConfigRequest msg1, in android.hardware.wifi.NanConfigRequestSupplemental msg2);
+  void createDataInterfaceRequest(in char cmdId, in String ifaceName);
+  void deleteDataInterfaceRequest(in char cmdId, in String ifaceName);
+  void disableRequest(in char cmdId);
+  void enableRequest(in char cmdId, in android.hardware.wifi.NanEnableRequest msg1, in android.hardware.wifi.NanConfigRequestSupplemental msg2);
+  void getCapabilitiesRequest(in char cmdId);
+  void initiateDataPathRequest(in char cmdId, in android.hardware.wifi.NanInitiateDataPathRequest msg);
+  void registerEventCallback(in android.hardware.wifi.IWifiNanIfaceEventCallback callback);
+  void respondToDataPathIndicationRequest(in char cmdId, in android.hardware.wifi.NanRespondToDataPathIndicationRequest msg);
+  void startPublishRequest(in char cmdId, in android.hardware.wifi.NanPublishRequest msg);
+  void startSubscribeRequest(in char cmdId, in android.hardware.wifi.NanSubscribeRequest msg);
+  void stopPublishRequest(in char cmdId, in byte sessionId);
+  void stopSubscribeRequest(in char cmdId, in byte sessionId);
+  void terminateDataPathRequest(in char cmdId, in int ndpInstanceId);
+  void transmitFollowupRequest(in char cmdId, in android.hardware.wifi.NanTransmitFollowupRequest msg);
+  const int MIN_DATA_PATH_CONFIG_PASSPHRASE_LENGTH = 8;
+  const int MAX_DATA_PATH_CONFIG_PASSPHRASE_LENGTH = 63;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl
new file mode 100644
index 0000000..591cd8c
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+interface IWifiNanIfaceEventCallback {
+  oneway void eventClusterEvent(in android.hardware.wifi.NanClusterEventInd event);
+  oneway void eventDataPathConfirm(in android.hardware.wifi.NanDataPathConfirmInd event);
+  oneway void eventDataPathRequest(in android.hardware.wifi.NanDataPathRequestInd event);
+  oneway void eventDataPathScheduleUpdate(in android.hardware.wifi.NanDataPathScheduleUpdateInd event);
+  oneway void eventDataPathTerminated(in int ndpInstanceId);
+  oneway void eventDisabled(in android.hardware.wifi.NanStatus status);
+  oneway void eventFollowupReceived(in android.hardware.wifi.NanFollowupReceivedInd event);
+  oneway void eventMatch(in android.hardware.wifi.NanMatchInd event);
+  oneway void eventMatchExpired(in byte discoverySessionId, in int peerId);
+  oneway void eventPublishTerminated(in byte sessionId, in android.hardware.wifi.NanStatus status);
+  oneway void eventSubscribeTerminated(in byte sessionId, in android.hardware.wifi.NanStatus status);
+  oneway void eventTransmitFollowup(in char id, in android.hardware.wifi.NanStatus status);
+  oneway void notifyCapabilitiesResponse(in char id, in android.hardware.wifi.NanStatus status, in android.hardware.wifi.NanCapabilities capabilities);
+  oneway void notifyConfigResponse(in char id, in android.hardware.wifi.NanStatus status);
+  oneway void notifyCreateDataInterfaceResponse(in char id, in android.hardware.wifi.NanStatus status);
+  oneway void notifyDeleteDataInterfaceResponse(in char id, in android.hardware.wifi.NanStatus status);
+  oneway void notifyDisableResponse(in char id, in android.hardware.wifi.NanStatus status);
+  oneway void notifyEnableResponse(in char id, in android.hardware.wifi.NanStatus status);
+  oneway void notifyInitiateDataPathResponse(in char id, in android.hardware.wifi.NanStatus status, in int ndpInstanceId);
+  oneway void notifyRespondToDataPathIndicationResponse(in char id, in android.hardware.wifi.NanStatus status);
+  oneway void notifyStartPublishResponse(in char id, in android.hardware.wifi.NanStatus status, in byte sessionId);
+  oneway void notifyStartSubscribeResponse(in char id, in android.hardware.wifi.NanStatus status, in byte sessionId);
+  oneway void notifyStopPublishResponse(in char id, in android.hardware.wifi.NanStatus status);
+  oneway void notifyStopSubscribeResponse(in char id, in android.hardware.wifi.NanStatus status);
+  oneway void notifyTerminateDataPathResponse(in char id, in android.hardware.wifi.NanStatus status);
+  oneway void notifyTransmitFollowupResponse(in char id, in android.hardware.wifi.NanStatus status);
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiP2pIface.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiP2pIface.aidl
new file mode 100644
index 0000000..5e9948e
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiP2pIface.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+interface IWifiP2pIface {
+  String getName();
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiRttController.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiRttController.aidl
new file mode 100644
index 0000000..730a055
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiRttController.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+interface IWifiRttController {
+  void disableResponder(in int cmdId);
+  void enableResponder(in int cmdId, in android.hardware.wifi.WifiChannelInfo channelHint, in int maxDurationInSeconds, in android.hardware.wifi.RttResponder info);
+  android.hardware.wifi.IWifiStaIface getBoundIface();
+  android.hardware.wifi.RttCapabilities getCapabilities();
+  android.hardware.wifi.RttResponder getResponderInfo();
+  void rangeCancel(in int cmdId, in android.hardware.wifi.MacAddress[] addrs);
+  void rangeRequest(in int cmdId, in android.hardware.wifi.RttConfig[] rttConfigs);
+  void registerEventCallback(in android.hardware.wifi.IWifiRttControllerEventCallback callback);
+  void setLci(in int cmdId, in android.hardware.wifi.RttLciInformation lci);
+  void setLcr(in int cmdId, in android.hardware.wifi.RttLcrInformation lcr);
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiRttControllerEventCallback.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiRttControllerEventCallback.aidl
new file mode 100644
index 0000000..a6a33fc
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiRttControllerEventCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+interface IWifiRttControllerEventCallback {
+  oneway void onResults(in int cmdId, in android.hardware.wifi.RttResult[] results);
+}
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
new file mode 100644
index 0000000..2f0dfa1
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+interface IWifiStaIface {
+  String getName();
+  void configureRoaming(in android.hardware.wifi.StaRoamingConfig config);
+  void disableLinkLayerStatsCollection();
+  void enableLinkLayerStatsCollection(in boolean debug);
+  void enableNdOffload(in boolean enable);
+  android.hardware.wifi.StaApfPacketFilterCapabilities getApfPacketFilterCapabilities();
+  android.hardware.wifi.StaBackgroundScanCapabilities getBackgroundScanCapabilities();
+  android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask getCapabilities();
+  android.hardware.wifi.WifiDebugRxPacketFateReport[] getDebugRxPacketFates();
+  android.hardware.wifi.WifiDebugTxPacketFateReport[] getDebugTxPacketFates();
+  byte[6] getFactoryMacAddress();
+  android.hardware.wifi.StaLinkLayerStats getLinkLayerStats();
+  android.hardware.wifi.StaRoamingCapabilities getRoamingCapabilities();
+  int[] getValidFrequenciesForBand(in android.hardware.wifi.WifiBand band);
+  void installApfPacketFilter(in byte[] program);
+  byte[] readApfPacketFilterData();
+  void registerEventCallback(in android.hardware.wifi.IWifiStaIfaceEventCallback callback);
+  void setMacAddress(in byte[6] mac);
+  void setRoamingState(in android.hardware.wifi.StaRoamingState state);
+  void setScanMode(in boolean enable);
+  void startBackgroundScan(in int cmdId, in android.hardware.wifi.StaBackgroundScanParameters params);
+  void startDebugPacketFateMonitoring();
+  void startRssiMonitoring(in int cmdId, in int maxRssi, in int minRssi);
+  void startSendingKeepAlivePackets(in int cmdId, in byte[] ipPacketData, in char etherType, in byte[6] srcAddress, in byte[6] dstAddress, in int periodInMs);
+  void stopBackgroundScan(in int cmdId);
+  void stopRssiMonitoring(in int cmdId);
+  void stopSendingKeepAlivePackets(in int cmdId);
+  @Backing(type="int") @VintfStability
+  enum StaIfaceCapabilityMask {
+    APF = 1,
+    BACKGROUND_SCAN = 2,
+    LINK_LAYER_STATS = 4,
+    RSSI_MONITOR = 8,
+    CONTROL_ROAMING = 16,
+    PROBE_IE_ALLOWLIST = 32,
+    SCAN_RAND = 64,
+    STA_5G = 128,
+    HOTSPOT = 256,
+    PNO = 512,
+    TDLS = 1024,
+    TDLS_OFFCHANNEL = 2048,
+    ND_OFFLOAD = 4096,
+    KEEP_ALIVE = 8192,
+    DEBUG_PACKET_FATE = 16384,
+  }
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl
new file mode 100644
index 0000000..48b85b0
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIfaceEventCallback.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+interface IWifiStaIfaceEventCallback {
+  oneway void onBackgroundFullScanResult(in int cmdId, in int bucketsScanned, in android.hardware.wifi.StaScanResult result);
+  oneway void onBackgroundScanFailure(in int cmdId);
+  oneway void onBackgroundScanResults(in int cmdId, in android.hardware.wifi.StaScanData[] scanDatas);
+  oneway void onRssiThresholdBreached(in int cmdId, in byte[6] currBssid, in int currRssi);
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IfaceConcurrencyType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IfaceConcurrencyType.aidl
new file mode 100644
index 0000000..0a3ad1a
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IfaceConcurrencyType.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum IfaceConcurrencyType {
+  STA = 0,
+  AP = 1,
+  AP_BRIDGED = 2,
+  P2P = 3,
+  NAN_IFACE = 4,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IfaceType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IfaceType.aidl
new file mode 100644
index 0000000..dbdc439
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IfaceType.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum IfaceType {
+  STA = 0,
+  AP = 1,
+  P2P = 2,
+  NAN_IFACE = 3,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/MacAddress.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/MacAddress.aidl
new file mode 100644
index 0000000..c4a0613
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/MacAddress.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable MacAddress {
+  byte[6] data;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBandIndex.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBandIndex.aidl
new file mode 100644
index 0000000..ca6c910
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBandIndex.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum NanBandIndex {
+  NAN_BAND_24GHZ = 0,
+  NAN_BAND_5GHZ = 1,
+  NAN_BAND_6GHZ = 2,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBandSpecificConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBandSpecificConfig.aidl
new file mode 100644
index 0000000..57540b3
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanBandSpecificConfig.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanBandSpecificConfig {
+  byte rssiClose;
+  byte rssiMiddle;
+  byte rssiCloseProximity;
+  char dwellTimeMs;
+  char scanPeriodSec;
+  boolean validDiscoveryWindowIntervalVal;
+  byte discoveryWindowIntervalVal;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCapabilities.aidl
new file mode 100644
index 0000000..c44654e
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCapabilities.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanCapabilities {
+  int maxConcurrentClusters;
+  int maxPublishes;
+  int maxSubscribes;
+  int maxServiceNameLen;
+  int maxMatchFilterLen;
+  int maxTotalMatchFilterLen;
+  int maxServiceSpecificInfoLen;
+  int maxExtendedServiceSpecificInfoLen;
+  int maxNdiInterfaces;
+  int maxNdpSessions;
+  int maxAppInfoLen;
+  int maxQueuedTransmitFollowupMsgs;
+  int maxSubscribeInterfaceAddresses;
+  android.hardware.wifi.NanCipherSuiteType supportedCipherSuites;
+  boolean instantCommunicationModeSupportFlag;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCipherSuiteType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCipherSuiteType.aidl
new file mode 100644
index 0000000..4450956
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanCipherSuiteType.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum NanCipherSuiteType {
+  NONE = 0,
+  SHARED_KEY_128_MASK = 1,
+  SHARED_KEY_256_MASK = 2,
+  PUBLIC_KEY_128_MASK = 4,
+  PUBLIC_KEY_256_MASK = 8,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanClusterEventInd.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanClusterEventInd.aidl
new file mode 100644
index 0000000..7a3ff81
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanClusterEventInd.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanClusterEventInd {
+  android.hardware.wifi.NanClusterEventType eventType;
+  byte[6] addr;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanClusterEventType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanClusterEventType.aidl
new file mode 100644
index 0000000..1dfa45f
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanClusterEventType.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum NanClusterEventType {
+  DISCOVERY_MAC_ADDRESS_CHANGED = 0,
+  STARTED_CLUSTER = 1,
+  JOINED_CLUSTER = 2,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanConfigRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanConfigRequest.aidl
new file mode 100644
index 0000000..5ead651
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanConfigRequest.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanConfigRequest {
+  byte masterPref;
+  boolean disableDiscoveryAddressChangeIndication;
+  boolean disableStartedClusterIndication;
+  boolean disableJoinedClusterIndication;
+  boolean includePublishServiceIdsInBeacon;
+  byte numberOfPublishServiceIdsInBeacon;
+  boolean includeSubscribeServiceIdsInBeacon;
+  byte numberOfSubscribeServiceIdsInBeacon;
+  char rssiWindowSize;
+  int macAddressRandomizationIntervalSec;
+  android.hardware.wifi.NanBandSpecificConfig[3] bandSpecificConfig;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanConfigRequestSupplemental.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanConfigRequestSupplemental.aidl
new file mode 100644
index 0000000..682699e
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanConfigRequestSupplemental.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanConfigRequestSupplemental {
+  int discoveryBeaconIntervalMs;
+  int numberOfSpatialStreamsInDiscovery;
+  boolean enableDiscoveryWindowEarlyTermination;
+  boolean enableRanging;
+  boolean enableInstantCommunicationMode;
+  int instantModeChannel;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathChannelCfg.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathChannelCfg.aidl
new file mode 100644
index 0000000..ce75288
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathChannelCfg.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum NanDataPathChannelCfg {
+  CHANNEL_NOT_REQUESTED = 0,
+  REQUEST_CHANNEL_SETUP = 1,
+  FORCE_CHANNEL_SETUP = 2,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathChannelInfo.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathChannelInfo.aidl
new file mode 100644
index 0000000..d111db7
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathChannelInfo.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanDataPathChannelInfo {
+  int channelFreq;
+  android.hardware.wifi.WifiChannelWidthInMhz channelBandwidth;
+  int numSpatialStreams;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathConfirmInd.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathConfirmInd.aidl
new file mode 100644
index 0000000..2e1e2ca
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathConfirmInd.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanDataPathConfirmInd {
+  int ndpInstanceId;
+  boolean dataPathSetupSuccess;
+  byte[6] peerNdiMacAddr;
+  byte[] appInfo;
+  android.hardware.wifi.NanStatus status;
+  android.hardware.wifi.NanDataPathChannelInfo[] channelInfo;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathRequestInd.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathRequestInd.aidl
new file mode 100644
index 0000000..74d5b73
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathRequestInd.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanDataPathRequestInd {
+  byte discoverySessionId;
+  byte[6] peerDiscMacAddr;
+  int ndpInstanceId;
+  boolean securityRequired;
+  byte[] appInfo;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathScheduleUpdateInd.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathScheduleUpdateInd.aidl
new file mode 100644
index 0000000..5fabf55
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathScheduleUpdateInd.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanDataPathScheduleUpdateInd {
+  byte[6] peerDiscoveryAddress;
+  android.hardware.wifi.NanDataPathChannelInfo[] channelInfo;
+  int[] ndpInstanceIds;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathSecurityConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathSecurityConfig.aidl
new file mode 100644
index 0000000..635dbce
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathSecurityConfig.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanDataPathSecurityConfig {
+  android.hardware.wifi.NanDataPathSecurityType securityType;
+  android.hardware.wifi.NanCipherSuiteType cipherType;
+  byte[32] pmk;
+  byte[] passphrase;
+  byte[16] scid;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathSecurityType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathSecurityType.aidl
new file mode 100644
index 0000000..64288ca
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDataPathSecurityType.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum NanDataPathSecurityType {
+  OPEN = 0,
+  PMK = 1,
+  PASSPHRASE = 2,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDebugConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDebugConfig.aidl
new file mode 100644
index 0000000..b84d891
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDebugConfig.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanDebugConfig {
+  boolean validClusterIdVals;
+  char clusterIdBottomRangeVal;
+  char clusterIdTopRangeVal;
+  boolean validIntfAddrVal;
+  byte[6] intfAddrVal;
+  boolean validOuiVal;
+  int ouiVal;
+  boolean validRandomFactorForceVal;
+  byte randomFactorForceVal;
+  boolean validHopCountForceVal;
+  byte hopCountForceVal;
+  boolean validDiscoveryChannelVal;
+  int[3] discoveryChannelMhzVal;
+  boolean validUseBeaconsInBandVal;
+  boolean[3] useBeaconsInBandVal;
+  boolean validUseSdfInBandVal;
+  boolean[3] useSdfInBandVal;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDiscoveryCommonConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDiscoveryCommonConfig.aidl
new file mode 100644
index 0000000..761cdbb
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanDiscoveryCommonConfig.aidl
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanDiscoveryCommonConfig {
+  byte sessionId;
+  char ttlSec;
+  char discoveryWindowPeriod;
+  byte discoveryCount;
+  byte[] serviceName;
+  android.hardware.wifi.NanMatchAlg discoveryMatchIndicator;
+  byte[] serviceSpecificInfo;
+  byte[] extendedServiceSpecificInfo;
+  byte[] rxMatchFilter;
+  byte[] txMatchFilter;
+  boolean useRssiThreshold;
+  boolean disableDiscoveryTerminationIndication;
+  boolean disableMatchExpirationIndication;
+  boolean disableFollowupReceivedIndication;
+  android.hardware.wifi.NanDataPathSecurityConfig securityConfig;
+  boolean rangingRequired;
+  int rangingIntervalMs;
+  android.hardware.wifi.NanRangingIndication configRangingIndications;
+  char distanceIngressCm;
+  char distanceEgressCm;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanEnableRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanEnableRequest.aidl
new file mode 100644
index 0000000..eaa009c
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanEnableRequest.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanEnableRequest {
+  boolean[3] operateInBand;
+  byte hopCountMax;
+  android.hardware.wifi.NanConfigRequest configParams;
+  android.hardware.wifi.NanDebugConfig debugConfigs;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanFollowupReceivedInd.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanFollowupReceivedInd.aidl
new file mode 100644
index 0000000..743ad9d
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanFollowupReceivedInd.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanFollowupReceivedInd {
+  byte discoverySessionId;
+  int peerId;
+  byte[6] addr;
+  boolean receivedInFaw;
+  byte[] serviceSpecificInfo;
+  byte[] extendedServiceSpecificInfo;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanInitiateDataPathRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanInitiateDataPathRequest.aidl
new file mode 100644
index 0000000..697e29a
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanInitiateDataPathRequest.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanInitiateDataPathRequest {
+  int peerId;
+  byte[6] peerDiscMacAddr;
+  android.hardware.wifi.NanDataPathChannelCfg channelRequestType;
+  int channel;
+  String ifaceName;
+  android.hardware.wifi.NanDataPathSecurityConfig securityConfig;
+  byte[] appInfo;
+  byte[] serviceNameOutOfBand;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanMatchAlg.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanMatchAlg.aidl
new file mode 100644
index 0000000..dab33ad
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanMatchAlg.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum NanMatchAlg {
+  MATCH_ONCE = 0,
+  MATCH_CONTINUOUS = 1,
+  MATCH_NEVER = 2,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanMatchInd.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanMatchInd.aidl
new file mode 100644
index 0000000..ae430c4
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanMatchInd.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanMatchInd {
+  byte discoverySessionId;
+  int peerId;
+  byte[6] addr;
+  byte[] serviceSpecificInfo;
+  byte[] extendedServiceSpecificInfo;
+  byte[] matchFilter;
+  boolean matchOccurredInBeaconFlag;
+  boolean outOfResourceFlag;
+  byte rssiValue;
+  android.hardware.wifi.NanCipherSuiteType peerCipherType;
+  boolean peerRequiresSecurityEnabledInNdp;
+  boolean peerRequiresRanging;
+  int rangingMeasurementInMm;
+  android.hardware.wifi.NanRangingIndication rangingIndicationType;
+  byte[] scid;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishRequest.aidl
new file mode 100644
index 0000000..d8d6b1b
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishRequest.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanPublishRequest {
+  android.hardware.wifi.NanDiscoveryCommonConfig baseConfigs;
+  android.hardware.wifi.NanPublishType publishType;
+  android.hardware.wifi.NanTxType txType;
+  boolean autoAcceptDataPathRequests;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishType.aidl
new file mode 100644
index 0000000..fc9b7a0
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanPublishType.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum NanPublishType {
+  UNSOLICITED = 0,
+  SOLICITED = 1,
+  UNSOLICITED_SOLICITED = 2,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanRangingIndication.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanRangingIndication.aidl
new file mode 100644
index 0000000..d03dffc
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanRangingIndication.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum NanRangingIndication {
+  CONTINUOUS_INDICATION_MASK = 1,
+  INGRESS_MET_MASK = 2,
+  EGRESS_MET_MASK = 4,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanRespondToDataPathIndicationRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanRespondToDataPathIndicationRequest.aidl
new file mode 100644
index 0000000..5542ff6
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanRespondToDataPathIndicationRequest.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanRespondToDataPathIndicationRequest {
+  boolean acceptRequest;
+  int ndpInstanceId;
+  String ifaceName;
+  android.hardware.wifi.NanDataPathSecurityConfig securityConfig;
+  byte[] appInfo;
+  byte[] serviceNameOutOfBand;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSrfType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSrfType.aidl
new file mode 100644
index 0000000..3c0583c
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSrfType.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum NanSrfType {
+  BLOOM_FILTER = 0,
+  PARTIAL_MAC_ADDR = 1,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanStatus.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanStatus.aidl
new file mode 100644
index 0000000..834558a
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanStatus.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanStatus {
+  android.hardware.wifi.NanStatusCode status;
+  String description;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanStatusCode.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanStatusCode.aidl
new file mode 100644
index 0000000..9eaf518
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanStatusCode.aidl
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum NanStatusCode {
+  SUCCESS = 0,
+  INTERNAL_FAILURE = 1,
+  PROTOCOL_FAILURE = 2,
+  INVALID_SESSION_ID = 3,
+  NO_RESOURCES_AVAILABLE = 4,
+  INVALID_ARGS = 5,
+  INVALID_PEER_ID = 6,
+  INVALID_NDP_ID = 7,
+  NAN_NOT_ALLOWED = 8,
+  NO_OTA_ACK = 9,
+  ALREADY_ENABLED = 10,
+  FOLLOWUP_TX_QUEUE_FULL = 11,
+  UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 12,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSubscribeRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSubscribeRequest.aidl
new file mode 100644
index 0000000..bf176a5
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSubscribeRequest.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanSubscribeRequest {
+  android.hardware.wifi.NanDiscoveryCommonConfig baseConfigs;
+  android.hardware.wifi.NanSubscribeType subscribeType;
+  android.hardware.wifi.NanSrfType srfType;
+  boolean srfRespondIfInAddressSet;
+  boolean shouldUseSrf;
+  boolean isSsiRequiredForMatch;
+  android.hardware.wifi.MacAddress[] intfAddr;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSubscribeType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSubscribeType.aidl
new file mode 100644
index 0000000..325e40b
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanSubscribeType.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum NanSubscribeType {
+  PASSIVE = 0,
+  ACTIVE = 1,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanTransmitFollowupRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanTransmitFollowupRequest.aidl
new file mode 100644
index 0000000..20c94d9
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanTransmitFollowupRequest.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable NanTransmitFollowupRequest {
+  byte discoverySessionId;
+  int peerId;
+  byte[6] addr;
+  boolean isHighPriority;
+  boolean shouldUseDiscoveryWindow;
+  byte[] serviceSpecificInfo;
+  byte[] extendedServiceSpecificInfo;
+  boolean disableFollowupResultIndication;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanTxType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanTxType.aidl
new file mode 100644
index 0000000..6f7696f
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/NanTxType.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum NanTxType {
+  BROADCAST = 0,
+  UNICAST = 1,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttBw.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttBw.aidl
new file mode 100644
index 0000000..bd7efff
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttBw.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum RttBw {
+  BW_5MHZ = 1,
+  BW_10MHZ = 2,
+  BW_20MHZ = 4,
+  BW_40MHZ = 8,
+  BW_80MHZ = 16,
+  BW_160MHZ = 32,
+  BW_320MHZ = 64,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl
new file mode 100644
index 0000000..cf64687
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable RttCapabilities {
+  boolean rttOneSidedSupported;
+  boolean rttFtmSupported;
+  boolean lciSupported;
+  boolean lcrSupported;
+  boolean responderSupported;
+  android.hardware.wifi.RttPreamble preambleSupport;
+  android.hardware.wifi.RttBw bwSupport;
+  byte mcVersion;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl
new file mode 100644
index 0000000..ccdf2ce
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable RttConfig {
+  byte[6] addr;
+  android.hardware.wifi.RttType type;
+  android.hardware.wifi.RttPeerType peer;
+  android.hardware.wifi.WifiChannelInfo channel;
+  int burstPeriod;
+  int numBurst;
+  int numFramesPerBurst;
+  int numRetriesPerRttFrame;
+  int numRetriesPerFtmr;
+  boolean mustRequestLci;
+  boolean mustRequestLcr;
+  int burstDuration;
+  android.hardware.wifi.RttPreamble preamble;
+  android.hardware.wifi.RttBw bw;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttLciInformation.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttLciInformation.aidl
new file mode 100644
index 0000000..0fcf151
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttLciInformation.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable RttLciInformation {
+  long latitude;
+  long longitude;
+  int altitude;
+  byte latitudeUnc;
+  byte longitudeUnc;
+  byte altitudeUnc;
+  android.hardware.wifi.RttMotionPattern motionPattern;
+  int floor;
+  int heightAboveFloor;
+  int heightUnc;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttLcrInformation.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttLcrInformation.aidl
new file mode 100644
index 0000000..c756dda
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttLcrInformation.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable RttLcrInformation {
+  byte[2] countryCode;
+  String civicInfo;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttMotionPattern.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttMotionPattern.aidl
new file mode 100644
index 0000000..7c8e369
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttMotionPattern.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum RttMotionPattern {
+  NOT_EXPECTED = 0,
+  EXPECTED = 1,
+  UNKNOWN = 2,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttPeerType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttPeerType.aidl
new file mode 100644
index 0000000..23fa7f6
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttPeerType.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum RttPeerType {
+  AP = 1,
+  STA = 2,
+  P2P_GO = 3,
+  P2P_CLIENT = 4,
+  NAN_TYPE = 5,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttPreamble.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttPreamble.aidl
new file mode 100644
index 0000000..02e6479
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttPreamble.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum RttPreamble {
+  LEGACY = 1,
+  HT = 2,
+  VHT = 4,
+  HE = 8,
+  EHT = 16,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResponder.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResponder.aidl
new file mode 100644
index 0000000..41463b5
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResponder.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable RttResponder {
+  android.hardware.wifi.WifiChannelInfo channel;
+  android.hardware.wifi.RttPreamble preamble;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl
new file mode 100644
index 0000000..743e0bd
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable RttResult {
+  byte[6] addr;
+  int burstNum;
+  int measurementNumber;
+  int successNumber;
+  byte numberPerBurstPeer;
+  android.hardware.wifi.RttStatus status;
+  byte retryAfterDuration;
+  android.hardware.wifi.RttType type;
+  int rssi;
+  int rssiSpread;
+  android.hardware.wifi.WifiRateInfo txRate;
+  android.hardware.wifi.WifiRateInfo rxRate;
+  long rtt;
+  long rttSd;
+  long rttSpread;
+  int distanceInMm;
+  int distanceSdInMm;
+  int distanceSpreadInMm;
+  long timeStampInUs;
+  int burstDurationInMs;
+  int negotiatedBurstNum;
+  android.hardware.wifi.WifiInformationElement lci;
+  android.hardware.wifi.WifiInformationElement lcr;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttStatus.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttStatus.aidl
new file mode 100644
index 0000000..2817497
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttStatus.aidl
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum RttStatus {
+  SUCCESS = 0,
+  FAILURE = 1,
+  FAIL_NO_RSP = 2,
+  FAIL_REJECTED = 3,
+  FAIL_NOT_SCHEDULED_YET = 4,
+  FAIL_TM_TIMEOUT = 5,
+  FAIL_AP_ON_DIFF_CHANNEL = 6,
+  FAIL_NO_CAPABILITY = 7,
+  ABORTED = 8,
+  FAIL_INVALID_TS = 9,
+  FAIL_PROTOCOL = 10,
+  FAIL_SCHEDULE = 11,
+  FAIL_BUSY_TRY_LATER = 12,
+  INVALID_REQ = 13,
+  NO_WIFI = 14,
+  FAIL_FTM_PARAM_OVERRIDE = 15,
+  NAN_RANGING_PROTOCOL_FAILURE = 16,
+  NAN_RANGING_CONCURRENCY_NOT_SUPPORTED = 17,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttType.aidl
new file mode 100644
index 0000000..2b6087a
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttType.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum RttType {
+  ONE_SIDED = 1,
+  TWO_SIDED = 2,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/Ssid.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/Ssid.aidl
new file mode 100644
index 0000000..98b523f
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/Ssid.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable Ssid {
+  byte[32] data;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaApfPacketFilterCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaApfPacketFilterCapabilities.aidl
new file mode 100644
index 0000000..3b4d785
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaApfPacketFilterCapabilities.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaApfPacketFilterCapabilities {
+  int version;
+  int maxLength;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanBucketEventReportSchemeMask.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanBucketEventReportSchemeMask.aidl
new file mode 100644
index 0000000..1041dd7
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanBucketEventReportSchemeMask.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum StaBackgroundScanBucketEventReportSchemeMask {
+  EACH_SCAN = 1,
+  FULL_RESULTS = 2,
+  NO_BATCH = 4,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanBucketParameters.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanBucketParameters.aidl
new file mode 100644
index 0000000..b49d406
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanBucketParameters.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaBackgroundScanBucketParameters {
+  int bucketIdx;
+  android.hardware.wifi.WifiBand band;
+  int[] frequencies;
+  int periodInMs;
+  android.hardware.wifi.StaBackgroundScanBucketEventReportSchemeMask eventReportScheme;
+  int exponentialMaxPeriodInMs;
+  int exponentialBase;
+  int exponentialStepCount;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanCapabilities.aidl
new file mode 100644
index 0000000..758dd97
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanCapabilities.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaBackgroundScanCapabilities {
+  int maxCacheSize;
+  int maxBuckets;
+  int maxApCachePerScan;
+  int maxReportingThreshold;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanLimits.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanLimits.aidl
new file mode 100644
index 0000000..05d0277
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanLimits.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum StaBackgroundScanLimits {
+  MAX_CHANNELS = 16,
+  MAX_BUCKETS = 16,
+  MAX_AP_CACHE_PER_SCAN = 32,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanParameters.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanParameters.aidl
new file mode 100644
index 0000000..0773566
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaBackgroundScanParameters.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaBackgroundScanParameters {
+  int basePeriodInMs;
+  int maxApPerScan;
+  int reportThresholdPercent;
+  int reportThresholdNumScans;
+  android.hardware.wifi.StaBackgroundScanBucketParameters[] buckets;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceContentionTimeStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceContentionTimeStats.aidl
new file mode 100644
index 0000000..4dee6de
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceContentionTimeStats.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaLinkLayerIfaceContentionTimeStats {
+  int contentionTimeMinInUsec;
+  int contentionTimeMaxInUsec;
+  int contentionTimeAvgInUsec;
+  int contentionNumSamples;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfacePacketStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfacePacketStats.aidl
new file mode 100644
index 0000000..eddf52e
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfacePacketStats.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaLinkLayerIfacePacketStats {
+  long rxMpdu;
+  long txMpdu;
+  long lostMpdu;
+  long retries;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceStats.aidl
new file mode 100644
index 0000000..cf68fc6
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceStats.aidl
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaLinkLayerIfaceStats {
+  int beaconRx;
+  int avgRssiMgmt;
+  android.hardware.wifi.StaLinkLayerIfacePacketStats wmeBePktStats;
+  android.hardware.wifi.StaLinkLayerIfacePacketStats wmeBkPktStats;
+  android.hardware.wifi.StaLinkLayerIfacePacketStats wmeViPktStats;
+  android.hardware.wifi.StaLinkLayerIfacePacketStats wmeVoPktStats;
+  byte timeSliceDutyCycleInPercent;
+  android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeBeContentionTimeStats;
+  android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeBkContentionTimeStats;
+  android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeViContentionTimeStats;
+  android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeVoContentionTimeStats;
+  android.hardware.wifi.StaPeerInfo[] peers;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerRadioStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerRadioStats.aidl
new file mode 100644
index 0000000..84d24c9
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerRadioStats.aidl
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaLinkLayerRadioStats {
+  int onTimeInMs;
+  int txTimeInMs;
+  int[] txTimeInMsPerLevel;
+  int rxTimeInMs;
+  int onTimeInMsForScan;
+  int onTimeInMsForNanScan;
+  int onTimeInMsForBgScan;
+  int onTimeInMsForRoamScan;
+  int onTimeInMsForPnoScan;
+  int onTimeInMsForHs20Scan;
+  android.hardware.wifi.WifiChannelStats[] channelStats;
+  int radioId;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerStats.aidl
new file mode 100644
index 0000000..9c05346
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerStats.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaLinkLayerStats {
+  android.hardware.wifi.StaLinkLayerIfaceStats iface;
+  android.hardware.wifi.StaLinkLayerRadioStats[] radios;
+  long timeStampInMs;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaPeerInfo.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaPeerInfo.aidl
new file mode 100644
index 0000000..93a901f
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaPeerInfo.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaPeerInfo {
+  char staCount;
+  char chanUtil;
+  android.hardware.wifi.StaRateStat[] rateStats;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaRateStat.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaRateStat.aidl
new file mode 100644
index 0000000..43b69fc
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaRateStat.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaRateStat {
+  android.hardware.wifi.WifiRateInfo rateInfo;
+  int txMpdu;
+  int rxMpdu;
+  int mpduLost;
+  int retries;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaRoamingCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaRoamingCapabilities.aidl
new file mode 100644
index 0000000..9eed877
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaRoamingCapabilities.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaRoamingCapabilities {
+  int maxBlocklistSize;
+  int maxAllowlistSize;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaRoamingConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaRoamingConfig.aidl
new file mode 100644
index 0000000..2b37cee
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaRoamingConfig.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaRoamingConfig {
+  android.hardware.wifi.MacAddress[] bssidBlocklist;
+  android.hardware.wifi.Ssid[] ssidAllowlist;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaRoamingState.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaRoamingState.aidl
new file mode 100644
index 0000000..1f3d91f
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaRoamingState.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="byte") @VintfStability
+enum StaRoamingState {
+  DISABLED = 0,
+  ENABLED = 1,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaScanData.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaScanData.aidl
new file mode 100644
index 0000000..5903760
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaScanData.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaScanData {
+  android.hardware.wifi.StaScanDataFlagMask flags;
+  int bucketsScanned;
+  android.hardware.wifi.StaScanResult[] results;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaScanDataFlagMask.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaScanDataFlagMask.aidl
new file mode 100644
index 0000000..dc8f2f1
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaScanDataFlagMask.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum StaScanDataFlagMask {
+  INTERRUPTED = 1,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaScanResult.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaScanResult.aidl
new file mode 100644
index 0000000..9a8d297
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaScanResult.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable StaScanResult {
+  long timeStampInUs;
+  byte[] ssid;
+  byte[6] bssid;
+  int rssi;
+  int frequency;
+  char beaconPeriodInMs;
+  char capability;
+  android.hardware.wifi.WifiInformationElement[] informationElements;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiAntennaMode.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiAntennaMode.aidl
new file mode 100644
index 0000000..b47b7f5
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiAntennaMode.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum WifiAntennaMode {
+  WIFI_ANTENNA_MODE_UNSPECIFIED = 0,
+  WIFI_ANTENNA_MODE_1X1 = 1,
+  WIFI_ANTENNA_MODE_2X2 = 2,
+  WIFI_ANTENNA_MODE_3X3 = 3,
+  WIFI_ANTENNA_MODE_4X4 = 4,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiBand.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiBand.aidl
new file mode 100644
index 0000000..e9a87ee
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiBand.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum WifiBand {
+  BAND_UNSPECIFIED = 0,
+  BAND_24GHZ = 1,
+  BAND_5GHZ = 2,
+  BAND_5GHZ_DFS = 4,
+  BAND_5GHZ_WITH_DFS = 6,
+  BAND_24GHZ_5GHZ = 3,
+  BAND_24GHZ_5GHZ_WITH_DFS = 7,
+  BAND_6GHZ = 8,
+  BAND_5GHZ_6GHZ = 10,
+  BAND_24GHZ_5GHZ_6GHZ = 11,
+  BAND_24GHZ_5GHZ_WITH_DFS_6GHZ = 15,
+  BAND_60GHZ = 16,
+  BAND_24GHZ_5GHZ_6GHZ_60GHZ = 27,
+  BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ = 31,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChannelInfo.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChannelInfo.aidl
new file mode 100644
index 0000000..297c923
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChannelInfo.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiChannelInfo {
+  android.hardware.wifi.WifiChannelWidthInMhz width;
+  int centerFreq;
+  int centerFreq0;
+  int centerFreq1;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChannelStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChannelStats.aidl
new file mode 100644
index 0000000..c6e7acc
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChannelStats.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiChannelStats {
+  android.hardware.wifi.WifiChannelInfo channel;
+  int onTimeInMs;
+  int ccaBusyTimeInMs;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChannelWidthInMhz.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChannelWidthInMhz.aidl
new file mode 100644
index 0000000..8c45044
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiChannelWidthInMhz.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum WifiChannelWidthInMhz {
+  WIDTH_INVALID = -1,
+  WIDTH_20 = 0,
+  WIDTH_40 = 1,
+  WIDTH_80 = 2,
+  WIDTH_160 = 3,
+  WIDTH_80P80 = 4,
+  WIDTH_5 = 5,
+  WIDTH_10 = 6,
+  WIDTH_320 = 7,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugHostWakeReasonRxIcmpPacketDetails.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugHostWakeReasonRxIcmpPacketDetails.aidl
new file mode 100644
index 0000000..8415e09
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugHostWakeReasonRxIcmpPacketDetails.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiDebugHostWakeReasonRxIcmpPacketDetails {
+  int icmpPkt;
+  int icmp6Pkt;
+  int icmp6Ra;
+  int icmp6Na;
+  int icmp6Ns;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugHostWakeReasonRxMulticastPacketDetails.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugHostWakeReasonRxMulticastPacketDetails.aidl
new file mode 100644
index 0000000..30301d3
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugHostWakeReasonRxMulticastPacketDetails.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiDebugHostWakeReasonRxMulticastPacketDetails {
+  int ipv4RxMulticastAddrCnt;
+  int ipv6RxMulticastAddrCnt;
+  int otherRxMulticastAddrCnt;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugHostWakeReasonRxPacketDetails.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugHostWakeReasonRxPacketDetails.aidl
new file mode 100644
index 0000000..8118322
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugHostWakeReasonRxPacketDetails.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiDebugHostWakeReasonRxPacketDetails {
+  int rxUnicastCnt;
+  int rxMulticastCnt;
+  int rxBroadcastCnt;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugHostWakeReasonStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugHostWakeReasonStats.aidl
new file mode 100644
index 0000000..1766476
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugHostWakeReasonStats.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiDebugHostWakeReasonStats {
+  int totalCmdEventWakeCnt;
+  int[] cmdEventWakeCntPerType;
+  int totalDriverFwLocalWakeCnt;
+  int[] driverFwLocalWakeCntPerType;
+  int totalRxPacketWakeCnt;
+  android.hardware.wifi.WifiDebugHostWakeReasonRxPacketDetails rxPktWakeDetails;
+  android.hardware.wifi.WifiDebugHostWakeReasonRxMulticastPacketDetails rxMulticastPkWakeDetails;
+  android.hardware.wifi.WifiDebugHostWakeReasonRxIcmpPacketDetails rxIcmpPkWakeDetails;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugPacketFateFrameInfo.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugPacketFateFrameInfo.aidl
new file mode 100644
index 0000000..2ff6cfc
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugPacketFateFrameInfo.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiDebugPacketFateFrameInfo {
+  android.hardware.wifi.WifiDebugPacketFateFrameType frameType;
+  long frameLen;
+  long driverTimestampUsec;
+  long firmwareTimestampUsec;
+  byte[] frameContent;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugPacketFateFrameType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugPacketFateFrameType.aidl
new file mode 100644
index 0000000..ee26f2e
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugPacketFateFrameType.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum WifiDebugPacketFateFrameType {
+  UNKNOWN = 0,
+  ETHERNET_II = 1,
+  MGMT_80211 = 2,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRingBufferFlags.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRingBufferFlags.aidl
new file mode 100644
index 0000000..f210e82
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRingBufferFlags.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum WifiDebugRingBufferFlags {
+  HAS_BINARY_ENTRIES = 1,
+  HAS_ASCII_ENTRIES = 2,
+  HAS_PER_PACKET_ENTRIES = 4,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRingBufferStatus.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRingBufferStatus.aidl
new file mode 100644
index 0000000..e4249d9
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRingBufferStatus.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiDebugRingBufferStatus {
+  String ringName;
+  int flags;
+  int ringId;
+  int sizeInBytes;
+  int freeSizeInBytes;
+  int verboseLevel;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRingBufferVerboseLevel.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRingBufferVerboseLevel.aidl
new file mode 100644
index 0000000..e614f3f
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRingBufferVerboseLevel.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum WifiDebugRingBufferVerboseLevel {
+  NONE = 0,
+  DEFAULT = 1,
+  VERBOSE = 2,
+  EXCESSIVE = 3,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRxPacketFate.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRxPacketFate.aidl
new file mode 100644
index 0000000..75abb4e
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRxPacketFate.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum WifiDebugRxPacketFate {
+  SUCCESS = 0,
+  FW_QUEUED = 1,
+  FW_DROP_FILTER = 2,
+  FW_DROP_INVALID = 3,
+  FW_DROP_NOBUFS = 4,
+  FW_DROP_OTHER = 5,
+  DRV_QUEUED = 6,
+  DRV_DROP_FILTER = 7,
+  DRV_DROP_INVALID = 8,
+  DRV_DROP_NOBUFS = 9,
+  DRV_DROP_OTHER = 10,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRxPacketFateReport.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRxPacketFateReport.aidl
new file mode 100644
index 0000000..bfe0c0a
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugRxPacketFateReport.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiDebugRxPacketFateReport {
+  android.hardware.wifi.WifiDebugRxPacketFate fate;
+  android.hardware.wifi.WifiDebugPacketFateFrameInfo frameInfo;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugTxPacketFate.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugTxPacketFate.aidl
new file mode 100644
index 0000000..e360c2c
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugTxPacketFate.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum WifiDebugTxPacketFate {
+  ACKED = 0,
+  SENT = 1,
+  FW_QUEUED = 2,
+  FW_DROP_INVALID = 3,
+  FW_DROP_NOBUFS = 4,
+  FW_DROP_OTHER = 5,
+  DRV_QUEUED = 6,
+  DRV_DROP_INVALID = 7,
+  DRV_DROP_NOBUFS = 8,
+  DRV_DROP_OTHER = 9,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugTxPacketFateReport.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugTxPacketFateReport.aidl
new file mode 100644
index 0000000..aee5c31
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiDebugTxPacketFateReport.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiDebugTxPacketFateReport {
+  android.hardware.wifi.WifiDebugTxPacketFate fate;
+  android.hardware.wifi.WifiDebugPacketFateFrameInfo frameInfo;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiIfaceMode.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiIfaceMode.aidl
new file mode 100644
index 0000000..e2fe57a
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiIfaceMode.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum WifiIfaceMode {
+  IFACE_MODE_STA = 1,
+  IFACE_MODE_SOFTAP = 2,
+  IFACE_MODE_IBSS = 4,
+  IFACE_MODE_P2P_CLIENT = 8,
+  IFACE_MODE_P2P_GO = 16,
+  IFACE_MODE_NAN = 32,
+  IFACE_MODE_MESH = 64,
+  IFACE_MODE_TDLS = 128,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiInformationElement.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiInformationElement.aidl
new file mode 100644
index 0000000..27ba0db
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiInformationElement.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiInformationElement {
+  byte id;
+  byte[] data;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRadioCombination.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRadioCombination.aidl
new file mode 100644
index 0000000..f060db8
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRadioCombination.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiRadioCombination {
+  android.hardware.wifi.WifiRadioConfiguration[] radioConfigurations;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRadioCombinationMatrix.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRadioCombinationMatrix.aidl
new file mode 100644
index 0000000..ea86c4f
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRadioCombinationMatrix.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiRadioCombinationMatrix {
+  android.hardware.wifi.WifiRadioCombination[] radioCombinations;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRadioConfiguration.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRadioConfiguration.aidl
new file mode 100644
index 0000000..5169351
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRadioConfiguration.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiRadioConfiguration {
+  android.hardware.wifi.WifiBand bandInfo;
+  android.hardware.wifi.WifiAntennaMode antennaMode;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRateInfo.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRateInfo.aidl
new file mode 100644
index 0000000..c4aca63
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRateInfo.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiRateInfo {
+  android.hardware.wifi.WifiRatePreamble preamble;
+  android.hardware.wifi.WifiRateNss nss;
+  android.hardware.wifi.WifiChannelWidthInMhz bw;
+  byte rateMcsIdx;
+  int bitRateInKbps;
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRateNss.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRateNss.aidl
new file mode 100644
index 0000000..0ad6f04
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRateNss.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum WifiRateNss {
+  NSS_1x1 = 0,
+  NSS_2x2 = 1,
+  NSS_3x3 = 2,
+  NSS_4x4 = 3,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRatePreamble.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRatePreamble.aidl
new file mode 100644
index 0000000..04b6358
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiRatePreamble.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum WifiRatePreamble {
+  OFDM = 0,
+  CCK = 1,
+  HT = 2,
+  VHT = 3,
+  RESERVED = 4,
+  HE = 5,
+  EHT = 6,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiStatusCode.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiStatusCode.aidl
new file mode 100644
index 0000000..f27661c
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiStatusCode.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@Backing(type="int") @VintfStability
+enum WifiStatusCode {
+  SUCCESS = 0,
+  ERROR_WIFI_CHIP_INVALID = 1,
+  ERROR_WIFI_IFACE_INVALID = 2,
+  ERROR_WIFI_RTT_CONTROLLER_INVALID = 3,
+  ERROR_NOT_SUPPORTED = 4,
+  ERROR_NOT_AVAILABLE = 5,
+  ERROR_NOT_STARTED = 6,
+  ERROR_INVALID_ARGS = 7,
+  ERROR_BUSY = 8,
+  ERROR_UNKNOWN = 9,
+}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiUsableChannel.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiUsableChannel.aidl
new file mode 100644
index 0000000..94e3a8a
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/WifiUsableChannel.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi;
+@VintfStability
+parcelable WifiUsableChannel {
+  int channel;
+  android.hardware.wifi.WifiChannelWidthInMhz channelBandwidth;
+  android.hardware.wifi.WifiIfaceMode ifaceModeMask;
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifi.aidl b/wifi/aidl/android/hardware/wifi/IWifi.aidl
new file mode 100644
index 0000000..1d86421
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IWifi.aidl
@@ -0,0 +1,100 @@
+/*
+ * 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;
+
+import android.hardware.wifi.IWifiChip;
+import android.hardware.wifi.IWifiEventCallback;
+
+/**
+ * This is the root of the HAL module and is the interface returned when
+ * loading an implementation of the Wi-Fi HAL. There must be at most one
+ * module loaded in the system.
+ */
+@VintfStability
+interface IWifi {
+    /**
+     * Gets an AIDL interface object for the chip corresponding to the
+     * provided chipId.
+     *
+     * @param chipId ID of the chip.
+     * @return AIDL interface object representing the chip.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.NOT_STARTED|,
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    @PropagateAllowBlocking IWifiChip getChip(int chipId);
+
+    /**
+     * Retrieves the list of all chip id's on the device.
+     * The corresponding |IWifiChip| object for any chip can be
+     * retrieved using the |getChip| method.
+     *
+     * @return List of all chip id's on the device.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.NOT_STARTED|,
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    int[] getChipIds();
+
+    /**
+     * Get the current state of the HAL.
+     *
+     * @return true if started, false otherwise.
+     */
+    boolean isStarted();
+
+    /**
+     * Requests notifications of significant HAL events. Multiple calls to
+     * this must register multiple callbacks, each of which must receive all
+     * events. |IWifiEventCallback| object registration must be independent of the
+     * state of the rest of the HAL and must persist though stops/starts. These
+     * objects must be deleted when the corresponding client process is dead.
+     *
+     * @param callback An instance of the |IWifiEventCallback| AIDL interface
+     *        object.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    void registerEventCallback(in IWifiEventCallback callback);
+
+    /**
+     * Perform any setup that is required to make use of the module.
+     * If the module is already started then this must be a noop.
+     * Must trigger |IWifiEventCallback.onStart| on success.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.NOT_AVAILABLE|,
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    void start();
+
+    /**
+     * Tear down any state, ongoing commands, etc. If the module is already
+     * stopped then this must be a noop. After calling this, all |IWifiChip|
+     * objects will be considered invalid.
+     * Must trigger |IWifiEventCallback.onStop| on success.
+     * Must trigger |IWifiEventCallback.onFailure| on failure.
+     *
+     * Calling stop() and then start() is a valid way of resetting state in
+     * the HAL, driver, and firmware.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.NOT_STARTED|,
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    void stop();
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl b/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl
new file mode 100644
index 0000000..71ea385
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl
@@ -0,0 +1,102 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiBand;
+
+/**
+ * Represents a network interface in AP mode.
+ *
+ * This can be obtained through |IWifiChip.getApIface|.
+ */
+@VintfStability
+interface IWifiApIface {
+    /**
+     * Get the name of this interface.
+     *
+     * @return Name of this interface.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|
+     */
+    String getName();
+
+    /**
+     * Get the names of the bridged AP instances.
+     *
+     * @return Vector containing the names of the bridged AP
+     *         instances. Note: Returns an empty vector for a non-bridged AP.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    String[] getBridgedInstances();
+
+    /**
+     * Gets the factory MAC address of the interface.
+     *
+     * @return Factory MAC address of the interface.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    byte[6] getFactoryMacAddress();
+
+    /**
+     * Set country code for this iface.
+     *
+     * @param code 2 byte country code (as defined in ISO 3166) to set.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.FAILURE_UNKNOWN|,
+     *         |WifiStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setCountryCode(in byte[2] code);
+
+    /**
+     * Used to query the list of valid frequencies (depending on country code set)
+     * for the provided band.
+     *
+     * @param band Band for which the frequency list is being generated.
+     * @return Vector of valid frequencies for the provided band.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    int[] getValidFrequenciesForBand(in WifiBand band);
+
+    /**
+     * Reset all of the AP interfaces' MAC address to the factory MAC address.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void resetToFactoryMacAddress();
+
+    /**
+     * Changes the MAC address of the interface to the given MAC address.
+     *
+     * @param mac MAC address to change to.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void setMacAddress(in byte[6] mac);
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiChip.aidl b/wifi/aidl/android/hardware/wifi/IWifiChip.aidl
new file mode 100644
index 0000000..fe9a6f3
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IWifiChip.aidl
@@ -0,0 +1,1096 @@
+/*
+ * 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;
+
+import android.hardware.wifi.IWifiApIface;
+import android.hardware.wifi.IWifiChipEventCallback;
+import android.hardware.wifi.IWifiNanIface;
+import android.hardware.wifi.IWifiP2pIface;
+import android.hardware.wifi.IWifiRttController;
+import android.hardware.wifi.IWifiStaIface;
+import android.hardware.wifi.IfaceConcurrencyType;
+import android.hardware.wifi.IfaceType;
+import android.hardware.wifi.WifiBand;
+import android.hardware.wifi.WifiDebugHostWakeReasonStats;
+import android.hardware.wifi.WifiDebugRingBufferStatus;
+import android.hardware.wifi.WifiDebugRingBufferVerboseLevel;
+import android.hardware.wifi.WifiIfaceMode;
+import android.hardware.wifi.WifiRadioCombinationMatrix;
+import android.hardware.wifi.WifiUsableChannel;
+
+/**
+ * Interface that represents a chip that must be configured as a single unit.
+ */
+@VintfStability
+interface IWifiChip {
+    /**
+     * Capabilities exposed by this chip.
+     */
+    @VintfStability
+    @Backing(type="int")
+    enum ChipCapabilityMask {
+        /**
+         * Memory dump of Firmware.
+         */
+        DEBUG_MEMORY_FIRMWARE_DUMP = 1 << 0,
+        /**
+         * Memory dump of Driver.
+         */
+        DEBUG_MEMORY_DRIVER_DUMP = 1 << 1,
+        /**
+         * Connectivity events reported via debug ring buffer.
+         */
+        DEBUG_RING_BUFFER_CONNECT_EVENT = 1 << 2,
+        /**
+         * Power events reported via debug ring buffer.
+         */
+        DEBUG_RING_BUFFER_POWER_EVENT = 1 << 3,
+        /**
+         * Wakelock events reported via debug ring buffer.
+         */
+        DEBUG_RING_BUFFER_WAKELOCK_EVENT = 1 << 4,
+        /**
+         * Vendor data reported via debug ring buffer.
+         * This mostly contains firmware event logs.
+         */
+        DEBUG_RING_BUFFER_VENDOR_DATA = 1 << 5,
+        /**
+         * Host wake reasons stats collection.
+         */
+        DEBUG_HOST_WAKE_REASON_STATS = 1 << 6,
+        /**
+         * Error alerts.
+         */
+        DEBUG_ERROR_ALERTS = 1 << 7,
+        /**
+         * Set/Reset Tx Power limits.
+         */
+        SET_TX_POWER_LIMIT = 1 << 8,
+        /**
+         * Device to Device RTT.
+         */
+        D2D_RTT = 1 << 9,
+        /**
+         * Device to AP RTT.
+         */
+        D2AP_RTT = 1 << 10,
+        /**
+         * Set/Reset Tx Power limits.
+         */
+        USE_BODY_HEAD_SAR = 1 << 11,
+        /**
+         * Set Latency Mode.
+         */
+        SET_LATENCY_MODE = 1 << 12,
+        /**
+         * Support P2P MAC randomization.
+         */
+        P2P_RAND_MAC = 1 << 13,
+        /**
+         * Chip can operate in the 60GHz band (WiGig chip).
+         */
+        WIGIG = 1 << 14,
+    }
+
+    /**
+     * Set of interface concurrency types, along with the maximum number of interfaces that can have
+     * one of the specified concurrency types for a given ChipConcurrencyCombination. See
+     * ChipConcurrencyCombination below for examples.
+     */
+    @VintfStability
+    parcelable ChipConcurrencyCombinationLimit {
+        IfaceConcurrencyType[] types;
+        int maxIfaces;
+    }
+
+    /**
+     * Set of interfaces that can operate concurrently when in a given mode. See
+     * ChipMode below.
+     *
+     * For example:
+     *   [{STA} <= 2]
+     *       At most two STA interfaces are supported
+     *       [], [STA], [STA+STA]
+     *
+     *   [{STA} <= 1, {NAN} <= 1, {AP_BRIDGED} <= 1]
+     *       Any combination of STA, NAN, AP_BRIDGED
+     *       [], [STA], [NAN], [AP_BRIDGED], [STA+NAN], [STA+AP_BRIDGED], [NAN+AP_BRIDGED],
+     *       [STA+NAN+AP_BRIDGED]
+     *
+     *   [{STA} <= 1, {NAN,P2P} <= 1]
+     *       Optionally a STA and either NAN or P2P
+     *       [], [STA], [STA+NAN], [STA+P2P], [NAN], [P2P]
+     *       Not included [NAN+P2P], [STA+NAN+P2P]
+     *
+     *   [{STA} <= 1, {STA,NAN} <= 1]
+     *       Optionally a STA and either a second STA or a NAN
+     *       [], [STA], [STA+NAN], [STA+STA], [NAN]
+     *       Not included [STA+STA+NAN]
+     */
+    @VintfStability
+    parcelable ChipConcurrencyCombination {
+        ChipConcurrencyCombinationLimit[] limits;
+    }
+
+    /**
+     * Information about the version of the driver and firmware running this chip.
+     *
+     * The information in these ASCII strings are vendor specific and does not
+     * need to follow any particular format. It may be dumped as part of the bug
+     * report.
+     */
+    @VintfStability
+    parcelable ChipDebugInfo {
+        String driverDescription;
+        String firmwareDescription;
+    }
+
+    /**
+     * Set of interface types, along with the maximum number of interfaces that can have
+     * one of the specified types for a given ChipIfaceCombination. See
+     * ChipIfaceCombination for examples.
+     */
+    @VintfStability
+    parcelable ChipIfaceCombinationLimit {
+        IfaceType[] types;
+        int maxIfaces;
+    }
+
+    /**
+     * Set of interfaces that can operate concurrently when in a given mode. See
+     * ChipMode below.
+     *
+     * For example:
+     *   [{STA} <= 2]
+     *       At most two STA interfaces are supported
+     *       [], [STA], [STA+STA]
+     *
+     *   [{STA} <= 1, {NAN} <= 1, {AP} <= 1]
+     *       Any combination of STA, NAN, AP
+     *       [], [STA], [NAN], [AP], [STA+NAN], [STA+AP], [NAN+AP], [STA+NAN+AP]
+     *
+     *   [{STA} <= 1, {NAN,P2P} <= 1]
+     *       Optionally a STA and either NAN or P2P
+     *       [], [STA], [STA+NAN], [STA+P2P], [NAN], [P2P]
+     *       Not included [NAN+P2P], [STA+NAN+P2P]
+     *
+     *   [{STA} <= 1, {STA,NAN} <= 1]
+     *       Optionally a STA and either a second STA or a NAN
+     *       [], [STA], [STA+NAN], [STA+STA], [NAN]
+     *       Not included [STA+STA+NAN]
+     */
+    @VintfStability
+    parcelable ChipIfaceCombination {
+        ChipIfaceCombinationLimit[] limits;
+    }
+
+    /**
+     * A mode that the chip can be put in. A mode defines a set of constraints on
+     * the interfaces that can exist while in that mode. Modes define a unit of
+     * configuration where all interfaces must be torn down to switch to a
+     * different mode. Some HALs may only have a single mode, but an example where
+     * multiple modes would be required is if a chip has different firmwares with
+     * different capabilities.
+     *
+     * When in a mode, it must be possible to perform any combination of creating
+     * and removing interfaces as long as at least one of the
+     * ChipConcurrencyCombinations is satisfied. This means that if a chip has two
+     * available combinations, [{STA} <= 1] and [{AP_BRIDGED} <= 1] then it is expected
+     * that exactly one STA type or one AP_BRIDGED type can be created, but it
+     * is not expected that both a STA and AP_BRIDGED type  could be created. If it
+     * was then there would be a single available combination
+     * [{STA} <=1, {AP_BRIDGED} <= 1].
+     *
+     * When switching between two available combinations it is expected that
+     * interfaces only supported by the initial combination must be removed until
+     * the target combination is also satisfied. At that point new interfaces
+     * satisfying only the target combination can be added (meaning the initial
+     * combination limits will no longer satisfied). The addition of these new
+     * interfaces must not impact the existence of interfaces that satisfy both
+     * combinations.
+     *
+     * For example, a chip with available combinations:
+     *     [{STA} <= 2, {NAN} <=1] and [{STA} <=1, {NAN} <= 1, {AP_BRIDGED} <= 1}]
+     * If the chip currently has 3 interfaces STA, STA and NAN and wants to add an
+     * AP_BRIDGED interface in place of one of the STAs, then one of the STA interfaces
+     * must be removed first, and then the AP interface can be created after
+     * the STA has been torn down. During this process the remaining STA and NAN
+     * interfaces must not be removed/recreated.
+     *
+     * If a chip does not support this kind of reconfiguration in this mode then
+     * the combinations must be separated into two separate modes. Before
+     * switching modes, all interfaces must be torn down, the mode switch must be
+     * enacted, and when it completes the new interfaces must be brought up.
+     */
+    @VintfStability
+    parcelable ChipMode {
+        /**
+         * Id that can be used to put the chip in this mode.
+         */
+        int id;
+        /**
+         * A list of the possible interface concurrency type combinations that the
+         * chip can have while in this mode.
+         */
+        ChipConcurrencyCombination[] availableCombinations;
+    }
+
+    /**
+     * Wi-Fi coex channel avoidance support.
+     */
+    const int NO_POWER_CAP_CONSTANT = 0x7FFFFFFF;
+
+    @VintfStability
+    @Backing(type="int")
+    enum CoexRestriction {
+        WIFI_DIRECT = 1 << 0,
+        SOFTAP = 1 << 1,
+        WIFI_AWARE = 1 << 2,
+    }
+
+    /**
+     * Representation of a Wi-Fi channel for Wi-Fi coex channel avoidance.
+     */
+    @VintfStability
+    parcelable CoexUnsafeChannel {
+        /*
+         * Band of the channel.
+         */
+        WifiBand band;
+        /*
+         * Channel number.
+         */
+        int channel;
+        /**
+         * The power cap will be a maximum power value in dbm that is allowed to be transmitted by
+         * the chip on this channel. A value of PowerCapConstant.NO_POWER_CAP means no limitation
+         * on transmitted power is needed by the chip for this channel.
+         */
+        int powerCapDbm;
+    }
+
+    /**
+     * This enum represents the different latency modes that can be set through |setLatencyMode|.
+     */
+    @VintfStability
+    @Backing(type="int")
+    enum LatencyMode {
+        NORMAL = 0,
+        LOW = 1,
+    }
+
+    /**
+     * When there are 2 or more simultaneous STA connections, this use case hint indicates what
+     * use-case is being enabled by the framework. This use case hint can be used by the firmware
+     * to modify various firmware configurations like:
+     *   - Allowed BSSIDs the firmware can choose for the initial connection/roaming attempts.
+     *   - Duty cycle to choose for the 2 STA connections if the radio is in MCC mode.
+     *   - Whether roaming, APF and other offloads need to be enabled or not.
+     * Note:
+     *   - This will be invoked before an active wifi connection is established on the second
+     *     interface.
+     *   - This use-case hint is implicitly void when the second STA interface is brought down.
+     *   - When there is only 1 STA interface, we should still retain the last use case
+     *     set, which must become active the next time multi STA is enabled.
+     *     1. Initialize with single STA.
+     *     2. Framework creates second STA.
+     *     3. Framework sets use case to DUAL_STA_NON_TRANSIENT_UNBIASED.
+     *     4. Framework destroys second STA. Only 1 STA remains.
+     *     5. Framework recreates second STA.
+     *     6. The active use case remains DUAL_STA_NON_TRANSIENT_UNBIASED (i.e. firmware should not
+     *        automatically change it during period of single STA unless requested by framework).
+     */
+    @VintfStability
+    @Backing(type="byte")
+    enum MultiStaUseCase {
+        /**
+         * Usage:
+         * - This will be sent down for make before break use-case.
+         * - Platform is trying to speculatively connect to a second network and evaluate it without
+         *  disrupting the primary connection.
+         * Requirements for Firmware:
+         * - Do not reduce the number of tx/rx chains of primary connection.
+         * - If using MCC, should set the MCC duty cycle of the primary connection to be higher than
+         *  the secondary connection (maybe 70/30 split).
+         * - Should pick the best BSSID for the secondary STA (disregard the chip mode) independent
+         *   of the primary STA:
+         *    - Don’t optimize for DBS vs MCC/SCC
+         * - Should not impact the primary connection’s bssid selection:
+         *    - Don’t downgrade chains of the existing primary connection.
+         *    - Don’t optimize for DBS vs MCC/SCC.
+         */
+        DUAL_STA_TRANSIENT_PREFER_PRIMARY = 0,
+        /**
+         * Usage:
+         * - This will be sent down for any app requested peer to peer connections.
+         * - In this case, both the connections need to be allocated equal resources.
+         * - For the peer to peer use case, BSSID for the secondary connection will be chosen by the
+         *   framework.
+         *
+         * Requirements for Firmware:
+         * - Can choose MCC or DBS mode depending on the MCC efficiency and HW capability.
+         * - If using MCC, set the MCC duty cycle of the primary connection to be equal to the
+         *   secondary connection.
+         * - Prefer BSSID candidates which will help provide the best "overall" performance for both
+         *   the connections.
+         */
+        DUAL_STA_NON_TRANSIENT_UNBIASED = 1,
+    }
+
+    /**
+     * List of preset wifi radio TX power levels for different scenarios.
+     * The actual power values (typically varies based on the channel,
+     * 802.11 connection type, number of MIMO streams, etc) for each scenario
+     * is defined by the OEM as a BDF file since it varies for each wifi chip
+     * vendor and device.
+     */
+    @VintfStability
+    @Backing(type="int")
+    enum TxPowerScenario {
+        VOICE_CALL = 0,
+        ON_HEAD_CELL_OFF = 1,
+        ON_HEAD_CELL_ON = 2,
+        ON_BODY_CELL_OFF = 3,
+        ON_BODY_CELL_ON = 4,
+    }
+
+    /**
+     * Usable Wifi channels filter masks.
+     */
+    @VintfStability
+    @Backing(type="int")
+    enum UsableChannelFilter {
+        /**
+         * Filter Wifi channels that should be avoided due to extreme
+         * cellular coexistence restrictions. Some Wifi channels can have
+         * extreme interference from/to cellular due to short frequency
+         * seperation with neighboring cellular channels, or when there
+         * is harmonic and intermodulation interference. Channels which
+         * only have some performance degradation (e.g. power back off is
+         * sufficient to deal with coexistence issue) can be included and
+         * should not be filtered out.
+         */
+        CELLULAR_COEXISTENCE = 1 << 0,
+        /**
+         * Filter based on concurrency state.
+         * Examples:
+         * - 5GHz SAP operation may be supported in standalone mode, but if
+         *  there is a STA connection on a 5GHz DFS channel, none of the 5GHz
+         *  channels are usable for SAP if device does not support DFS SAP mode.
+         * - P2P GO may not be supported on indoor channels in the EU during
+         *  standalone mode but if there is a STA connection on indoor channel.
+         *  P2P GO may be supported by some vendors on the same STA channel.
+         */
+        CONCURRENCY = 1 << 1,
+        /**
+         * Filter Wifi channels that are supported for NAN 3.1 Instant communication mode.
+         * This filter should only be applied to a NAN interface.
+         * - If 5G is supported, then default discovery channel 149/44 is considered.
+         * - If 5G is not supported, then channel 6 has to be considered.
+         */
+        NAN_INSTANT_MODE = 1 << 2,
+    }
+
+    /**
+     * Configure the Chip.
+     * This may NOT be called to reconfigure a chip due to an internal
+     * limitation. Calling this when chip is already configured in a different
+     * mode must trigger an ERROR_NOT_SUPPORTED failure.
+     * If you want to do reconfiguration, please call |IWifi.stop| and |IWifi.start|
+     * to restart Wifi HAL before calling this.
+     * Any existing |IWifiIface| objects must be marked invalid after this call.
+     * If this fails then the chip is now in an undefined state and
+     * configureChip must be called again.
+     * Must trigger |IWifiChipEventCallback.onChipReconfigured| on success.
+     * Must trigger |IWifiEventCallback.onFailure| on failure.
+     *
+     * @param modeId Mode that the chip must switch to, corresponding to the
+     *        id property of the target ChipMode.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void configureChip(in int modeId);
+
+    /**
+     * Create an AP iface on the chip.
+     *
+     * Depending on the mode the chip is configured in, the interface creation
+     * may fail (code: |WifiStatusCode.ERROR_NOT_AVAILABLE|) if we've already
+     * reached the maximum allowed (specified in |ChipIfaceCombination|) number
+     * of ifaces of the AP type.
+     *
+     * @return AIDL interface object representing the iface if
+     *         successful, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|
+     */
+    @PropagateAllowBlocking IWifiApIface createApIface();
+
+    /**
+     * Create a bridged AP iface on the chip.
+     *
+     * Depending on the mode the chip is configured in, the interface creation
+     * may fail (code: |WifiStatusCode.ERROR_NOT_AVAILABLE|) if we've already
+     * reached the maximum allowed (specified in |ChipIfaceCombination|) number
+     * of ifaces of the AP type.
+     *
+     * @return AIDL interface object representing the iface if
+     *         successful, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|
+     */
+    @PropagateAllowBlocking IWifiApIface createBridgedApIface();
+
+    /**
+     * Create a NAN iface on the chip.
+     *
+     * Depending on the mode the chip is configured in, the interface creation
+     * may fail (code: |WifiStatusCode.ERROR_NOT_AVAILABLE|) if we've already
+     * reached the maximum allowed (specified in |ChipIfaceCombination|) number
+     * of ifaces of the NAN type.
+     *
+     * @return AIDL interface object representing the iface if
+     *         successful, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|
+     */
+    @PropagateAllowBlocking IWifiNanIface createNanIface();
+
+    /**
+     * Create a P2P iface on the chip.
+     *
+     * Depending on the mode the chip is configured in, the interface creation
+     * may fail (code: |WifiStatusCode.ERROR_NOT_AVAILABLE|) if we've already
+     * reached the maximum allowed (specified in |ChipIfaceCombination|) number
+     * of ifaces of the P2P type.
+     *
+     * @return AIDL interface object representing the iface if
+     *         successful, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|
+     */
+    @PropagateAllowBlocking IWifiP2pIface createP2pIface();
+
+    /**
+     * Create an RTTController instance.
+     *
+     * RTT controller can be either:
+     * a) Bound to a specific STA iface by passing in the corresponding
+     * |IWifiStaIface| object in the |boundIface| param, OR
+     * b) Let the implementation decide the iface to use for RTT operations
+     * by passing null in the |boundIface| param.
+     *
+     * @param boundIface AIDL interface object representing the STA iface if
+     *        the responder must be bound to a specific iface, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|
+     */
+    @PropagateAllowBlocking IWifiRttController createRttController(in IWifiStaIface boundIface);
+
+    /**
+     * Create a STA iface on the chip.
+     *
+     * Depending on the mode the chip is configured in, the interface creation
+     * may fail (code: |WifiStatusCode.ERROR_NOT_AVAILABLE|) if we've already
+     * reached the maximum allowed (specified in |ChipIfaceCombination|) number
+     * of ifaces of the STA type.
+     *
+     * @return AIDL interface object representing the iface if
+     *         successful, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|
+     */
+    @PropagateAllowBlocking IWifiStaIface createStaIface();
+
+    /**
+     * API to enable/disable alert notifications from the chip.
+     * These alerts must be used to notify the framework of any fatal error events
+     * that the chip encounters via |IWifiChipEventCallback.onDebugErrorAlert| method.
+     * Must fail if |ChipCapabilityMask.DEBUG_ERROR_ALERTS| is not set.
+     *
+     * @param enable true to enable, false to disable.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.NOT_AVAILABLE|,
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    void enableDebugErrorAlerts(in boolean enable);
+
+    /**
+     * API to flush debug ring buffer data to files.
+     *
+     * Force flush debug ring buffer using IBase::debug.
+     * This API helps to collect firmware/driver/pkt logs.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    void flushRingBufferToFile();
+
+    /**
+     * API to force dump data into the corresponding ring buffer.
+     * This is to be invoked during bugreport collection.
+     *
+     * @param ringName Name of the ring for which data collection should
+     *        be forced. This can be retrieved via the corresponding
+     *        |WifiDebugRingBufferStatus|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_STARTED|,
+     *         |WifiStatusCode.NOT_AVAILABLE|,
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    void forceDumpToDebugRingBuffer(in String ringName);
+
+    /**
+     * Gets an AIDL interface object for the AP Iface corresponding
+     * to the provided ifname.
+     *
+     * @param ifname Name of the iface.
+     * @return AIDL interface object representing the iface if
+     *         it exists, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|
+     */
+    @PropagateAllowBlocking IWifiApIface getApIface(in String ifname);
+
+    /**
+     * List all the AP iface names configured on the chip.
+     * The corresponding |IWifiApIface| object for any iface
+     * can be retrieved using the |getApIface| method.
+     *
+     * @return List of all AP iface names on the chip.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|
+     */
+    String[] getApIfaceNames();
+
+    /**
+     * Get the set of operation modes that the chip supports.
+     *
+     * @return List of modes supported by the device.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|
+     */
+    ChipMode[] getAvailableModes();
+
+    /**
+     * Get the capabilities supported by this chip.
+     *
+     * @return Bitset of |ChipCapabilityMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    ChipCapabilityMask getCapabilities();
+
+    /**
+     * API to retrieve the wifi wake up reason stats for debugging.
+     * The driver is expected to start maintaining these stats once the chip
+     * is configured using |configureChip|. These stats must be reset whenever
+     * the chip is reconfigured or the HAL is stopped.
+     *
+     * @return Instance of |WifiDebugHostWakeReasonStats|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.NOT_AVAILABLE|,
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    WifiDebugHostWakeReasonStats getDebugHostWakeReasonStats();
+
+    /**
+     * The WiFi debug ring buffer life cycle is as follows:
+     * - At initialization, the framework must call |getDebugRingBuffersStatus|.
+     *   to obtain the names and list of supported ring buffers.
+     *   The driver may expose several different rings, each holding a different
+     *   type of data (connection events, power events, etc).
+     * - When WiFi operations start, the framework must call
+     *   |startLoggingToDebugRingBuffer| to trigger log collection for a specific
+     *   ring. The vebose level for each ring buffer can be specified in this API.
+     * - During wifi operations, the driver must periodically report per ring data
+     *   to framework by invoking the
+     *   |IWifiChipEventCallback.onDebugRingBufferDataAvailable| callback.
+     * - When capturing a bug report, the framework must indicate to driver that
+     *   all the data has to be uploaded urgently by calling |forceDumpToDebugRingBuffer|.
+     *
+     * The data uploaded by driver must be stored by the framework in separate files,
+     * with one stream of file per ring. The framework must store the files in pcapng
+     * format, allowing for easy merging and parsing with network analyzer tools.
+     * TODO: Since we're no longer dumping the raw data, storing in separate
+     * pcapng files for parsing later must not work anymore.
+     */
+
+    /*
+     * API to get the status of all ring buffers supported by driver.
+     *
+     * @return Vector of |WifiDebugRingBufferStatus| corresponding to the
+     *         status of each ring buffer on the device.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.NOT_AVAILABLE|,
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    WifiDebugRingBufferStatus[] getDebugRingBuffersStatus();
+
+    /**
+     * Get the Id assigned to this chip.
+     *
+     * @return Assigned chip Id.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|
+     */
+    int getId();
+
+    /**
+     * Get the current mode that the chip is in.
+     *
+     * @return Mode that the chip is currently configured to,
+     *         corresponding to the Id property of the target ChipMode.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|
+     */
+    int getMode();
+
+    /**
+     * Gets an AIDL interface object for the NAN Iface corresponding
+     * to the provided ifname.
+     *
+     * @param ifname Name of the iface.
+     * @return AIDL interface object representing the iface if
+     *         it exists, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|
+     */
+    @PropagateAllowBlocking IWifiNanIface getNanIface(in String ifname);
+
+    /**
+     * List all the NAN iface names configured on the chip.
+     * The corresponding |IWifiNanIface| object for any iface can
+     * be retrieved using the |getNanIface| method.
+     *
+     * @return List of all NAN iface names on the chip.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|
+     */
+    String[] getNanIfaceNames();
+
+    /**
+     * Gets an AIDL interface object for the P2P Iface corresponding
+     * to the provided ifname.
+     *
+     * @param ifname Name of the iface.
+     * @return AIDL interface object representing the iface if
+     *         it exists, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|
+     */
+    @PropagateAllowBlocking IWifiP2pIface getP2pIface(in String ifname);
+
+    /**
+     * List all the P2P iface names configured on the chip.
+     * The corresponding |IWifiP2pIface| object for any iface can
+     * be retrieved using the |getP2pIface| method.
+     *
+     * @return List of all P2P iface names on the chip.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|
+     */
+    String[] getP2pIfaceNames();
+
+    /**
+     * Gets an AIDL interface object for the STA Iface corresponding
+     * to the provided ifname.
+     *
+     * @param ifname Name of the iface.
+     * @return AIDL interface object representing the iface if
+     *         it exists, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|
+     */
+    @PropagateAllowBlocking IWifiStaIface getStaIface(in String ifname);
+
+    /**
+     * List all the STA iface names configured on the chip.
+     * The corresponding |IWifiStaIface| object for any iface can
+     * be retrieved using the |getStaIface| method.
+     *
+     * @param List of all STA iface names on the chip.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|
+     */
+    String[] getStaIfaceNames();
+
+    /**
+     * Retrieve the list of all the possible radio combinations supported by this
+     * chip.
+     *
+     * @return A list of all the possible radio combinations represented by
+     *         |WifiRadioCombinationMatrix|.
+     *         For example, in case of a chip which has two radios, where one radio is
+     *         capable of 2.4GHz 2X2 only and another radio which is capable of either
+     *         5GHz or 6GHz 2X2, the number of possible radio combinations in this case
+     *         is 5 and the possible combinations are:
+     *         {{{2G 2X2}}, //Standalone 2G
+     *         {{5G 2X2}}, //Standalone 5G
+     *         {{6G 2X2}}, //Standalone 6G
+     *         {{2G 2X2}, {5G 2X2}}, //2G+5G DBS
+     *         {{2G 2X2}, {6G 2X2}}} //2G+6G DBS
+     *         Note: Since this chip doesn’t support 5G+6G simultaneous operation,
+     *         as there is only one radio which can support both bands, it can only
+     *         do MCC 5G+6G. This table should not get populated with possible MCC
+     *         configurations. This is only for simultaneous radio configurations
+     *         (such as standalone, multi band simultaneous or single band simultaneous).
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.FAILURE_UNKNOWN|
+     *
+     */
+    WifiRadioCombinationMatrix getSupportedRadioCombinationsMatrix();
+
+    /**
+     * Retrieve a list of usable Wifi channels for the specified band &
+     * operational modes.
+     *
+     * The list of usable Wifi channels in a given band depends on factors
+     * like current country code, operational mode (e.g. STA, SAP, WFD-CLI,
+     * WFD-GO, TDLS, NAN) and other restrictons due to DFS, cellular coexistence
+     * and concurrency state of the device.
+     *
+     * @param band |WifiBand| for which list of usable channels is requested.
+     * @param ifaceModeMask Bitmask of the modes represented by |WifiIfaceMode|.
+     *        Bitmask respresents all the modes that the caller is interested
+     *        in (e.g. STA, SAP, CLI, GO, TDLS, NAN). E.g. If the caller is
+     *        interested in knowing usable channels for P2P CLI, P2P GO & NAN,
+     *        ifaceModeMask would be set to
+     *        IFACE_MODE_P2P_CLIENT|IFACE_MODE_P2P_GO|IFACE_MODE_NAN.
+     * @param filterMask Bitmask of filters represented by
+     *        |UsableChannelFilter|. Specifies whether driver should filter
+     *        channels based on additional criteria. If no filter is specified,
+     *        then the driver should return usable channels purely based on
+     *        regulatory constraints.
+     * @return List of channels represented by |WifiUsableChannel|.
+     *         Each entry represents a channel frequency, bandwidth and
+     *         bitmask of modes (e.g. STA, SAP, CLI, GO, TDLS, NAN) that are
+     *         allowed on that channel. E.g. If only STA mode can be supported
+     *         on an indoor channel, only the IFACE_MODE_STA bit would be set
+     *         for that channel. If 5GHz SAP cannot be supported, then none of
+     *         the 5GHz channels will have IFACE_MODE_SOFTAP bit set.
+     *         Note: Bits do not represent concurrency state. Each bit only
+     *         represents whether a particular mode is allowed on that channel.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.FAILURE_UNKNOWN|
+     */
+    WifiUsableChannel[] getUsableChannels(
+            in WifiBand band, in WifiIfaceMode ifaceModeMask, in UsableChannelFilter filterMask);
+
+    /**
+     * Requests notifications of significant events on this chip. Multiple calls
+     * to this must register multiple callbacks, each of which must receive all
+     * events.
+     *
+     * @param callback An instance of the |IWifiChipEventCallback| AIDL interface
+     *        object.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|
+     */
+    void registerEventCallback(in IWifiChipEventCallback callback);
+
+    /**
+     * Removes the AP Iface with the provided ifname.
+     * Any further calls on the corresponding |IWifiApIface| AIDL interface
+     * object must fail.
+     *
+     * @param ifname Name of the iface.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|
+     */
+    void removeApIface(in String ifname);
+
+    /**
+     * Removes an instance of AP iface with name |ifaceInstanceName| from the
+     * bridge AP with name |brIfaceName|.
+     *
+     * Use the API |removeApIface| with the brIfaceName to remove the bridge iface.
+     *
+     * @param brIfaceName Name of the bridged AP iface.
+     * @param ifaceInstanceName Name of the AP instance. The empty instance is
+     *        invalid.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|
+     */
+    void removeIfaceInstanceFromBridgedApIface(in String brIfaceName, in String ifaceInstanceName);
+
+    /**
+     * Removes the NAN Iface with the provided ifname.
+     * Any further calls on the corresponding |IWifiNanIface| AIDL interface
+     * object must fail.
+     *
+     * @param ifname Name of the iface.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|
+     */
+    void removeNanIface(in String ifname);
+
+    /**
+     * Removes the P2P Iface with the provided ifname.
+     * Any further calls on the corresponding |IWifiP2pIface| AIDL interface
+     * object must fail.
+     *
+     * @param ifname Name of the iface.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|
+     */
+    void removeP2pIface(in String ifname);
+
+    /**
+     * Removes the STA Iface with the provided ifname.
+     * Any further calls on the corresponding |IWifiStaIface| AIDL interface
+     * object must fail.
+     *
+     * @param ifname Name of the iface.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|
+     */
+    void removeStaIface(in String ifname);
+
+    /**
+     * Request information about the chip.
+     *
+     * @return Instance of |ChipDebugInfo|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    ChipDebugInfo requestChipDebugInfo();
+
+    /**
+     * Request vendor debug info from the driver.
+     *
+     * @return Vector of bytes retrieved from the driver.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    byte[] requestDriverDebugDump();
+
+    /**
+     * Request vendor debug info from the firmware.
+     *
+     * @return Vector of bytes retrieved from the firmware.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    byte[] requestFirmwareDebugDump();
+
+    /**
+     * API to reset TX power levels.
+     * This is used to indicate the end of the previously selected TX power
+     * scenario and let the wifi chip fall back to the default power values.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.NOT_AVAILABLE|,
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    void resetTxPowerScenario();
+
+    /**
+     * API to select one of the preset TX power scenarios.
+     *
+     * The framework must invoke this method with the appropriate scenario to let
+     * the wifi chip change its transmitting power levels.
+     * OEM's should define various power profiles for each of the scenarios
+     * above (defined in |TxPowerScenario|) in a vendor extension.
+     *
+     * @param scenario One of the preselected scenarios defined in
+     *        |TxPowerScenario|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.NOT_AVAILABLE|,
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    void selectTxPowerScenario(in TxPowerScenario scenario);
+
+    /**
+     * Invoked to indicate that the provided |CoexUnsafeChannels| should be avoided with the
+     * specified restrictions.
+     *
+     * Channel avoidance is a suggestion and should be done on a best-effort approach. If a provided
+     * channel is used, then the specified power cap should be applied.
+     *
+     * In addition, hard restrictions on the Wifi modes may be indicated by |CoexRestriction| bits
+     * (WIFI_DIRECT, SOFTAP, WIFI_AWARE) in the |restrictions| bitfield. If a hard restriction is
+     * provided, then the channels should be completely avoided for the provided Wifi modes instead
+     * of by best-effort.
+     *
+     * @param unsafeChannels List of |CoexUnsafeChannels| to avoid.
+     * @param restrictions Bitset of |CoexRestriction| values indicating Wifi interfaces to
+     *         completely avoid.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     */
+    void setCoexUnsafeChannels(
+            in CoexUnsafeChannel[] unsafeChannels, in CoexRestriction restrictions);
+
+    /**
+     * Set country code for this Wifi chip.
+     *
+     * Country code is global setting across the Wifi chip and not Wifi
+     * interface (STA or AP) specific.
+     *
+     * @param code 2 byte country code (as defined in ISO 3166) to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.FAILURE_UNKNOWN|,
+     *         |WifiStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setCountryCode(in byte[2] code);
+
+    /**
+     * API to set the wifi latency mode
+     *
+     * The latency mode is a hint to the HAL to enable or disable Wi-Fi latency
+     * optimization. The optimization should be enabled if the mode is set to |LOW|
+     * and should be disabled if the mode is set to |NORMAL|.
+     * Wi-Fi latency optimization may trade-off latency against other Wi-Fi
+     * functionality such as scanning, roaming, etc. but it should not result in
+     * completely halting this functionality.
+     *
+     * The low latency mode targets applications such as gaming and virtual reality.
+     */
+    void setLatencyMode(in LatencyMode mode);
+
+    /**
+     * Invoked to indicate that the provided iface is the primary STA iface when more
+     * than 1 STA ifaces are concurrently active.
+     * Notes:
+     * - If the wifi firmware/chip cannot support multiple instances of any offload
+     *   (like roaming, APF, rssi threshold, etc), the firmware should ensure that these
+     *   offloads are at least enabled for the primary interface. If the new primary interface is
+     *   already connected to a network, the firmware must switch all the offloads on
+     *   this new interface without disconnecting.
+     * - When there is only 1 STA interface, the firmware must still retain the last primary
+     *   connection, which must become active the next time multi STA is enabled.
+     *
+     * @param ifname Name of the STA iface.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|
+     */
+    void setMultiStaPrimaryConnection(in String ifName);
+
+    /**
+     * Invoked to indicate the STA + STA use-case that is active.
+     *
+     * Refer to documentation of |MultiStaUseCase| for details.
+     *
+     * @param useCase Use case that is active.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|
+     */
+    void setMultiStaUseCase(in MultiStaUseCase useCase);
+
+    /**
+     * API to trigger the debug data collection.
+     *
+     * @param ringName Name of the ring for which data collection
+     *        shall start. This can be retrieved via the corresponding
+     *        |WifiDebugRingBufferStatus|.
+     * @param verboseLevel Verbose level for logging.
+     * @parm maxIntervalInSec Maximum interval in seconds for driver to invoke
+     *       |onDebugRingBufferData|, ignore if zero.
+     * @parm minDataSizeInBytes: Minimum data size in buffer for driver to invoke
+     *       |onDebugRingBufferData|, ignore if zero.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.NOT_AVAILABLE|,
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    void startLoggingToDebugRingBuffer(in String ringName,
+            in WifiDebugRingBufferVerboseLevel verboseLevel, in int maxIntervalInSec,
+            in int minDataSizeInBytes);
+
+    /**
+     * API to stop the debug data collection for all ring buffers.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.NOT_AVAILABLE|,
+     *         |WifiStatusCode.UNKNOWN|
+     */
+    void stopLoggingToDebugRingBuffer();
+
+    /**
+     * Trigger subsystem restart.
+     *
+     * If the framework detects a problem (e.g. connection failure),
+     * it must call this function to attempt recovery.
+     *
+     * When the wifi HAL receives |triggerSubsystemRestart|, it must restart
+     * the wlan subsystem, especially the wlan firmware.
+     *
+     * Regarding the callback function for subsystem restart, refer to documentation of
+     * |IWifiEventCallback.onSubsystemRestart| for details.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void triggerSubsystemRestart();
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiChipEventCallback.aidl b/wifi/aidl/android/hardware/wifi/IWifiChipEventCallback.aidl
new file mode 100644
index 0000000..2bc4c0e
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IWifiChipEventCallback.aidl
@@ -0,0 +1,159 @@
+/*
+ * 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;
+
+import android.hardware.wifi.IfaceType;
+import android.hardware.wifi.WifiBand;
+import android.hardware.wifi.WifiDebugRingBufferStatus;
+import android.hardware.wifi.WifiStatusCode;
+
+/**
+ * Wifi chip event callbacks.
+ */
+@VintfStability
+oneway interface IWifiChipEventCallback {
+    /**
+     * Struct describing the state of each iface operating on the radio chain
+     * (hardware MAC) on the device.
+     */
+    @VintfStability
+    parcelable IfaceInfo {
+        /**
+         * Name of the interface (ex. wlan0).
+         */
+        String name;
+        /**
+         * Wifi channel on which this interface is operating.
+         */
+        int channel;
+    }
+
+    /**
+     * Struct describing the state of each hardware radio chain (hardware MAC)
+     * on the device.
+     */
+    @VintfStability
+    parcelable RadioModeInfo {
+        /**
+         * Identifier for this radio chain. This is vendor dependent and used
+         * only for debugging purposes.
+         */
+        int radioId;
+        /**
+         * List of bands on which this radio chain is operating.
+         * Can be one of:
+         * a) |WifiBand.BAND_24GHZ| => 2.4Ghz.
+         * b) |WifiBand.BAND_5GHZ| => 5Ghz.
+         * c) |WifiBand.BAND_24GHZ_5GHZ| => 2.4Ghz + 5Ghz (Radio is time sharing
+         * across the 2 bands).
+         * d) |WifiBand.BAND_6GHZ| => 6Ghz.
+         * e) |WifiBand.BAND_5GHZ_6GHZ| => 5Ghz + 6Ghz (Radio is time sharing
+         * across the 2 bands).
+         * f) |WifiBand.BAND_24GHZ_5GHZ_6GHZ| => 2.4Ghz + 5Ghz + 6Ghz (Radio is
+         * time sharing across the 3 bands).
+         */
+        WifiBand bandInfo;
+        /**
+         * List of interfaces on this radio chain (hardware MAC).
+         */
+        IfaceInfo[] ifaceInfos;
+    }
+
+    /**
+     * Callback indicating that a chip reconfiguration failed. This is a fatal
+     * error and any iface objects available previously must be considered
+     * invalid. The client can attempt to recover by trying to reconfigure the
+     * chip again using |IWifiChip.configureChip|.
+     *
+     * @param status Failure reason code.
+     */
+    void onChipReconfigureFailure(in WifiStatusCode status);
+
+    /**
+     * Callback indicating that the chip has been reconfigured successfully. At
+     * this point the interfaces available in the mode must be able to be
+     * configured. When this is called, any previous iface objects must be
+     * considered invalid.
+     *
+     * @param modeId The mode that the chip switched to, corresponding to the id
+     *        property of the target ChipMode.
+     */
+    void onChipReconfigured(in int modeId);
+
+    /**
+     * Callback indicating that the chip has encountered a fatal error.
+     * Client must not attempt to parse either the errorCode or debugData.
+     * Must only be captured in a bugreport.
+     *
+     * @param errorCode Vendor defined error code.
+     * @param debugData Vendor defined data used for debugging.
+     */
+    void onDebugErrorAlert(in int errorCode, in byte[] debugData);
+
+    /**
+     * Callbacks for reporting debug ring buffer data.
+     *
+     * The ring buffer data collection is event based:
+     * - Driver calls this callback when new records are available, the
+     *   |WifiDebugRingBufferStatus| passed up to framework in the callback
+     *   indicates to framework if more data is available in the ring buffer.
+     *   It is not expected that driver will necessarily always empty the ring
+     *   immediately as data is available. Instead the driver will report data
+     *   every X seconds, or if N bytes are available, based on the parameters
+     *   set via |startLoggingToDebugRingBuffer|.
+     * - In the case where a bug report has to be captured, the framework will
+     *   require driver to upload all data immediately. This is indicated to
+     *   driver when framework calls |forceDumpToDebugRingBuffer|. The driver
+     *   will start sending all available data in the indicated ring by repeatedly
+     *   invoking this callback.
+     *
+     * @param status Status of the corresponding ring buffer. This should
+     *         contain the name of the ring buffer on which the data is
+     *         available.
+     * @param data Raw bytes of data sent by the driver. Must be dumped
+     *         out to a bugreport and post processed.
+     */
+    void onDebugRingBufferDataAvailable(in WifiDebugRingBufferStatus status, in byte[] data);
+
+    /**
+     * Callback indicating that a new iface has been added to the chip.
+     *
+     * @param type Type of iface added.
+     * @param name Name of iface added.
+     */
+    void onIfaceAdded(in IfaceType type, in String name);
+
+    /**
+     * Callback indicating that an existing iface has been removed from the chip.
+     *
+     * @param type Type of iface removed.
+     * @param name Name of iface removed.
+     */
+    void onIfaceRemoved(in IfaceType type, in String name);
+
+    /**
+     * Indicates a radio mode change.
+     * Radio mode change could be a result of:
+     * a) Bringing up concurrent interfaces (ex. STA + AP).
+     * b) Change in operating band of one of the concurrent interfaces
+     * ( ex. STA connection moved from 2.4G to 5G)
+     *
+     * @param radioModeInfos List of RadioModeInfo structures for each
+     *        radio chain (hardware MAC) on the device.
+     */
+    void onRadioModeChange(in RadioModeInfo[] radioModeInfos);
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiEventCallback.aidl b/wifi/aidl/android/hardware/wifi/IWifiEventCallback.aidl
new file mode 100644
index 0000000..761bbf5
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IWifiEventCallback.aidl
@@ -0,0 +1,53 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiStatusCode;
+
+@VintfStability
+oneway interface IWifiEventCallback {
+    /**
+     * Called when the Wi-Fi system failed in a way that caused it be disabled.
+     * Calling start again must restart Wi-Fi as if stop then start was called
+     * (full state reset). When this event is received all IWifiChip & IWifiIface
+     * objects retrieved after the last call to start will be considered invalid.
+     *
+     * @param status Failure reason code.
+     */
+    void onFailure(in WifiStatusCode status);
+
+    /**
+     * Called in response to a call to start indicating that the operation
+     * completed. After this callback the HAL must be fully operational.
+     */
+    void onStart();
+
+    /**
+     * Called in response to a call to stop indicating that the operation
+     * completed. When this event is received all IWifiChip objects retrieved
+     * after the last call to start will be considered invalid.
+     */
+    void onStop();
+
+    /**
+     * Must be called when the Wi-Fi subsystem restart completes.
+     * Once this event is received, framework must fully reset the Wi-Fi stack state.
+     *
+     * @param status Status code.
+     */
+    void onSubsystemRestart(in WifiStatusCode status);
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiNanIface.aidl b/wifi/aidl/android/hardware/wifi/IWifiNanIface.aidl
new file mode 100644
index 0000000..45644b4
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IWifiNanIface.aidl
@@ -0,0 +1,251 @@
+/*
+ * 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;
+
+import android.hardware.wifi.IWifiNanIfaceEventCallback;
+import android.hardware.wifi.NanConfigRequest;
+import android.hardware.wifi.NanConfigRequestSupplemental;
+import android.hardware.wifi.NanEnableRequest;
+import android.hardware.wifi.NanInitiateDataPathRequest;
+import android.hardware.wifi.NanPublishRequest;
+import android.hardware.wifi.NanRespondToDataPathIndicationRequest;
+import android.hardware.wifi.NanSubscribeRequest;
+import android.hardware.wifi.NanTransmitFollowupRequest;
+
+/**
+ * Interface used to represent a single NAN (Neighbour Aware Network) iface.
+ *
+ * References to "NAN Spec" are to the Wi-Fi Alliance "Wi-Fi Neighbor Awareness
+ * Networking (NAN) Technical Specification".
+ */
+@VintfStability
+interface IWifiNanIface {
+    /**
+     * Minimum length of Passphrase argument for a data-path configuration.
+     */
+    const int MIN_DATA_PATH_CONFIG_PASSPHRASE_LENGTH = 8;
+
+    /**
+     * Maximum length of Passphrase argument for a data-path configuration.
+     */
+    const int MAX_DATA_PATH_CONFIG_PASSPHRASE_LENGTH = 63;
+
+    /**
+     * Get the name of this iface.
+     *
+     * @return Name of this iface.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|
+     */
+    String getName();
+
+    /**
+     * Configures an existing NAN functionality (i.e. assumes
+     * |IWifiNanIface.enableRequest| already submitted and succeeded).
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyConfigResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param msg1 Instance of |NanConfigRequest|.
+     * @param msg2 Instance of |NanConfigRequestSupplemental|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void configRequest(
+            in char cmdId, in NanConfigRequest msg1, in NanConfigRequestSupplemental msg2);
+
+    /**
+     * Create a NAN Data Interface.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyCreateDataInterfaceResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void createDataInterfaceRequest(in char cmdId, in String ifaceName);
+
+    /**
+     * Delete a NAN Data Interface.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyDeleteDataInterfaceResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void deleteDataInterfaceRequest(in char cmdId, in String ifaceName);
+
+    /**
+     * Disable NAN functionality.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyDisableResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void disableRequest(in char cmdId);
+
+    /**
+     * Configures and activates NAN clustering (does not start
+     * a discovery session or set up data-interfaces or data-paths). Use the
+     * |IWifiNanIface.configureRequest| method to change the configuration of an already enabled
+     * NAN interface.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyEnableResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param msg1 Instance of |NanEnableRequest|.
+     * @param msg2 Instance of |NanConfigRequestSupplemental|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void enableRequest(
+            in char cmdId, in NanEnableRequest msg1, in NanConfigRequestSupplemental msg2);
+
+    /**
+     * Get NAN capabilities. Asynchronous response is with
+     * |IWifiNanIfaceEventCallback.notifyCapabilitiesResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void getCapabilitiesRequest(in char cmdId);
+
+    /**
+     * Initiate a data-path (NDP) setup operation: Initiator.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyInitiateDataPathResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param msg Instance of |NanInitiateDataPathRequest|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void initiateDataPathRequest(in char cmdId, in NanInitiateDataPathRequest msg);
+
+    /**
+     * Requests notifications of significant events on this iface. Multiple calls
+     * to this must register multiple callbacks, each of which must receive all
+     * events.
+     *
+     * @param callback An instance of the |IWifiNanIfaceEventCallback| AIDL interface
+     *        object.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|
+     */
+    void registerEventCallback(in IWifiNanIfaceEventCallback callback);
+
+    /**
+     * Respond to a received data indication as part of a data-path (NDP) setup operation.
+     * An indication is received by the Responder from the Initiator.
+     * Asynchronous response is with
+     * |IWifiNanIfaceEventCallback.notifyRespondToDataPathIndicationResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param msg Instance of |NanRespondToDataPathIndicationRequest|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void respondToDataPathIndicationRequest(
+            in char cmdId, in NanRespondToDataPathIndicationRequest msg);
+
+    /**
+     * Publish request to start advertising a discovery service.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyStartPublishResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param msg Instance of |NanPublishRequest|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void startPublishRequest(in char cmdId, in NanPublishRequest msg);
+
+    /**
+     * Subscribe request to start searching for a discovery service.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyStartSubscribeResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param msg Instance of |NanSubscribeRequest|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void startSubscribeRequest(in char cmdId, in NanSubscribeRequest msg);
+
+    /**
+     * Stop publishing a discovery service.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyStopPublishResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param sessionId ID of the publish discovery session to be stopped.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void stopPublishRequest(in char cmdId, in byte sessionId);
+
+    /**
+     * Stop subscribing to a discovery service.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyStopSubscribeResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param sessionId ID of the subscribe discovery session to be stopped.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void stopSubscribeRequest(in char cmdId, in byte sessionId);
+
+    /**
+     * Data-path (NDP) termination request. Executed by either Initiator or Responder.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyTerminateDataPathResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param ndpInstanceId Data-path instance ID to be terminated.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void terminateDataPathRequest(in char cmdId, in int ndpInstanceId);
+
+    /**
+     * NAN transmit follow up message request.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyTransmitFollowupResponse|.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param msg Instance of |NanTransmitFollowupRequest|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void transmitFollowupRequest(in char cmdId, in NanTransmitFollowupRequest msg);
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl b/wifi/aidl/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl
new file mode 100644
index 0000000..470b7ba
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IWifiNanIfaceEventCallback.aidl
@@ -0,0 +1,322 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanCapabilities;
+import android.hardware.wifi.NanClusterEventInd;
+import android.hardware.wifi.NanDataPathConfirmInd;
+import android.hardware.wifi.NanDataPathRequestInd;
+import android.hardware.wifi.NanDataPathScheduleUpdateInd;
+import android.hardware.wifi.NanFollowupReceivedInd;
+import android.hardware.wifi.NanMatchInd;
+import android.hardware.wifi.NanStatus;
+
+/**
+ * NAN Response and Asynchronous Event Callbacks.
+ *
+ * References to "NAN Spec" are to the Wi-Fi Alliance "Wi-Fi Neighbor Awareness
+ * Networking (NAN) Technical Specification".
+ */
+@VintfStability
+oneway interface IWifiNanIfaceEventCallback {
+    /**
+     * Callback indicating that a cluster event has been received.
+     *
+     * @param event NanClusterEventInd containing event details.
+     */
+    void eventClusterEvent(in NanClusterEventInd event);
+
+    /**
+     * Callback indicating that a data-path (NDP) setup has been completed.
+     * Received by both Initiator and Responder.
+     *
+     * @param event NanDataPathConfirmInd containing event details.
+     */
+    void eventDataPathConfirm(in NanDataPathConfirmInd event);
+
+    /**
+     * Callback indicating that a data-path (NDP) setup has been requested by
+     * an Initiator peer (received by the intended Responder).
+     *
+     * @param event NanDataPathRequestInd containing event details.
+     */
+    void eventDataPathRequest(in NanDataPathRequestInd event);
+
+    /**
+     * Callback indicating that a data-path (NDP) schedule has been updated
+     * (e.g. channels have been changed).
+     *
+     * @param event NanDataPathScheduleUpdateInd containing event details.
+     */
+    void eventDataPathScheduleUpdate(in NanDataPathScheduleUpdateInd event);
+
+    /**
+     * Callback indicating that a list of data-paths (NDP) have been terminated.
+     * Received by both Initiator and Responder.
+     *
+     * @param ndpInstanceId Data-path ID of the terminated data-path.
+     */
+    void eventDataPathTerminated(in int ndpInstanceId);
+
+    /**
+     * Callback indicating that a NAN has been disabled.
+     *
+     * @param status NanStatus describing the reason for the disable event.
+     *               Possible status codes are:
+     *               |NanStatusCode.SUCCESS|
+     *               |NanStatusCode.UNSUPPORTED_CONCURRENCY_NAN_DISABLED|
+     */
+    void eventDisabled(in NanStatus status);
+
+    /**
+     * Callback indicating that a followup message has been received from a peer.
+     *
+     * @param event NanFollowupReceivedInd containing event details.
+     */
+    void eventFollowupReceived(in NanFollowupReceivedInd event);
+
+    /**
+     * Callback indicating that a match has occurred: i.e. a service has been
+     * discovered.
+     *
+     * @param event NanMatchInd containing event details.
+     */
+    void eventMatch(in NanMatchInd event);
+
+    /**
+     * Callback indicating that a previously discovered match (service) has expired.
+     *
+     * @param discoverySessionId Discovery session ID of the expired match.
+     * @param peerId Peer ID of the expired match.
+     */
+    void eventMatchExpired(in byte discoverySessionId, in int peerId);
+
+    /**
+     * Callback indicating that an active publish session has terminated.
+     *
+     * @param sessionId Discovery session ID of the terminated session.
+     * @param status NanStatus describing the reason for the session termination.
+     *               Possible status codes are:
+     *               |NanStatusCode.SUCCESS|
+     */
+    void eventPublishTerminated(in byte sessionId, in NanStatus status);
+
+    /**
+     * Callback indicating that an active subscribe session has terminated.
+     *
+     * @param sessionId Discovery session ID of the terminated session.
+     * @param status NanStatus describing the reason for the session termination.
+     *               Possible status codes are:
+     *               |NanStatusCode.SUCCESS|
+     */
+    void eventSubscribeTerminated(in byte sessionId, in NanStatus status);
+
+    /**
+     * Callback providing status on a completed followup message transmit operation.
+     *
+     * @param cmdId Command Id corresponding to the original |transmitFollowupRequest| request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *               |NanStatusCode.SUCCESS|
+     *               |NanStatusCode.NO_OTA_ACK|
+     *               |NanStatusCode.PROTOCOL_FAILURE|
+     */
+    void eventTransmitFollowup(in char id, in NanStatus status);
+
+    /**
+     * Callback invoked in response to a capability request
+     * |IWifiNanIface.getCapabilitiesRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     * @param capabilities Capability data.
+     */
+    void notifyCapabilitiesResponse(
+            in char id, in NanStatus status, in NanCapabilities capabilities);
+
+    /**
+     * Callback invoked in response to a config request |IWifiNanIface.configRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     *        |NanStatusCode.PROTOCOL_FAILURE|
+     */
+    void notifyConfigResponse(in char id, in NanStatus status);
+
+    /**
+     * Callback invoked in response to a create data interface request
+     * |IWifiNanIface.createDataInterfaceRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     */
+    void notifyCreateDataInterfaceResponse(in char id, in NanStatus status);
+
+    /**
+     * Callback invoked in response to a delete data interface request
+     * |IWifiNanIface.deleteDataInterfaceRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     */
+    void notifyDeleteDataInterfaceResponse(in char id, in NanStatus status);
+
+    /**
+     * Callback invoked in response to a disable request |IWifiNanIface.disableRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.PROTOCOL_FAILURE|
+     */
+    void notifyDisableResponse(in char id, in NanStatus status);
+
+    /**
+     * Callback invoked in response to an enable request |IWifiNanIface.enableRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.ALREADY_ENABLED|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     *        |NanStatusCode.PROTOCOL_FAILURE|
+     *        |NanStatusCode.NAN_NOT_ALLOWED|
+     */
+    void notifyEnableResponse(in char id, in NanStatus status);
+
+    /**
+     * Callback invoked in response to an initiate data path request
+     * |IWifiNanIface.initiateDataPathRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     *        |NanStatusCode.PROTOCOL_FAILURE|
+     *        |NanStatusCode.INVALID_PEER_ID|
+     * @param ndpInstanceId ID of the new data path being negotiated (on successful status).
+     */
+    void notifyInitiateDataPathResponse(in char id, in NanStatus status, in int ndpInstanceId);
+
+    /**
+     * Callback invoked in response to a respond to data path indication request
+     * |IWifiNanIface.respondToDataPathIndicationRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     *        |NanStatusCode.PROTOCOL_FAILURE|
+     *        |NanStatusCode.INVALID_NDP_ID|
+     */
+    void notifyRespondToDataPathIndicationResponse(in char id, in NanStatus status);
+
+    /**
+     * Callback invoked to notify the status of the start publish request
+     * |IWifiNanIface.startPublishRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.PROTOCOL_FAILURE|
+     *        |NanStatusCode.NO_RESOURCES_AVAILABLE|
+     *        |NanStatusCode.INVALID_SESSION_ID|
+     * @param sessionId ID of the new publish session (if successfully created).
+     */
+    void notifyStartPublishResponse(in char id, in NanStatus status, in byte sessionId);
+
+    /**
+     * Callback invoked to notify the status of the start subscribe request
+     * |IWifiNanIface.startSubscribeRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.PROTOCOL_FAILURE|
+     *        |NanStatusCode.NO_RESOURCES_AVAILABLE|
+     *        |NanStatusCode.INVALID_SESSION_ID|
+     * @param sessionId ID of the new subscribe session (if successfully created).
+     */
+    void notifyStartSubscribeResponse(in char id, in NanStatus status, in byte sessionId);
+
+    /**
+     * Callback invoked in response to a stop publish request
+     * |IWifiNanIface.stopPublishRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_SESSION_ID|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     */
+    void notifyStopPublishResponse(in char id, in NanStatus status);
+
+    /**
+     * Callback invoked in response to a stop subscribe request
+     * |IWifiNanIface.stopSubscribeRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_SESSION_ID|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     */
+    void notifyStopSubscribeResponse(in char id, in NanStatus status);
+
+    /**
+     * Callback invoked in response to a terminate data path request
+     * |IWifiNanIface.terminateDataPathRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     *        |NanStatusCode.PROTOCOL_FAILURE|
+     *        |NanStatusCode.INVALID_NDP_ID|
+     */
+    void notifyTerminateDataPathResponse(in char id, in NanStatus status);
+
+    /**
+     * Callback invoked in response to a transmit followup request
+     * |IWifiNanIface.transmitFollowupRequest|.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param status NanStatus of the operation. Possible status codes are:
+     *        |NanStatusCode.SUCCESS|
+     *        |NanStatusCode.INVALID_ARGS|
+     *        |NanStatusCode.INTERNAL_FAILURE|
+     *        |NanStatusCode.INVALID_SESSION_ID|
+     *        |NanStatusCode.INVALID_PEER_ID|
+     *        |NanStatusCode.FOLLOWUP_TX_QUEUE_FULL|
+     */
+    void notifyTransmitFollowupResponse(in char id, in NanStatus status);
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiP2pIface.aidl b/wifi/aidl/android/hardware/wifi/IWifiP2pIface.aidl
new file mode 100644
index 0000000..287f41d
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IWifiP2pIface.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.wifi;
+
+/**
+ * Interface used to represent a single P2P iface.
+ */
+@VintfStability
+interface IWifiP2pIface {
+    /**
+     * Get the name of this iface.
+     *
+     * @return Name of this iface.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|
+     */
+    String getName();
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiRttController.aidl b/wifi/aidl/android/hardware/wifi/IWifiRttController.aidl
new file mode 100644
index 0000000..99e1a81
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IWifiRttController.aidl
@@ -0,0 +1,158 @@
+/*
+ * 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;
+
+import android.hardware.wifi.IWifiRttControllerEventCallback;
+import android.hardware.wifi.IWifiStaIface;
+import android.hardware.wifi.MacAddress;
+import android.hardware.wifi.RttCapabilities;
+import android.hardware.wifi.RttConfig;
+import android.hardware.wifi.RttLciInformation;
+import android.hardware.wifi.RttLcrInformation;
+import android.hardware.wifi.RttResponder;
+import android.hardware.wifi.WifiChannelInfo;
+
+/**
+ * Interface used to perform RTT (Round trip time) operations.
+ */
+@VintfStability
+interface IWifiRttController {
+    /**
+     * Disable RTT responder mode.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void disableResponder(in int cmdId);
+
+    /**
+     * Enable RTT responder mode.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @parm channelHint Hint for the channel information where RTT responder
+     *       must be enabled on.
+     * @param maxDurationInSeconds Timeout of responder mode.
+     * @param info Instance of |RttResponderInfo|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void enableResponder(in int cmdId, in WifiChannelInfo channelHint, in int maxDurationInSeconds,
+            in RttResponder info);
+
+    /**
+     * Get the iface on which the RTT operations must be performed.
+     *
+     * @return AIDL interface object representing the iface if bound
+     *         to a specific iface, null otherwise
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|
+     */
+    IWifiStaIface getBoundIface();
+
+    /**
+     * RTT capabilities of the device.
+     *
+     * @return Instance of |RttCapabilities|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    RttCapabilities getCapabilities();
+
+    /**
+     * Get RTT responder information (e.g. WiFi channel) to enable responder on.
+     *
+     * @return Instance of |RttResponderInfo|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    RttResponder getResponderInfo();
+
+    /**
+     * API to cancel RTT measurements.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param addrs Vector of addresses for which to cancel.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void rangeCancel(in int cmdId, in MacAddress[] addrs);
+
+    /**
+     * API to request RTT measurement.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param rttConfigs Vector of |RttConfig| parameters.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void rangeRequest(in int cmdId, in RttConfig[] rttConfigs);
+
+    /**
+     * Requests notifications of significant events on this RTT controller.
+     * Multiple calls to this must register multiple callbacks, each of which
+     * must receive all events.
+     *
+     * @param callback An instance of the |IWifiRttControllerEventCallback| AIDL
+     *        interface object.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|
+     */
+    void registerEventCallback(in IWifiRttControllerEventCallback callback);
+
+    /**
+     * API to configure the LCI (Location civic information).
+     * Used in RTT Responder mode only.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param lci Instance of |RttLciInformation|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void setLci(in int cmdId, in RttLciInformation lci);
+
+    /**
+     * API to configure the LCR (Location civic records).
+     * Used in RTT Responder mode only.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param lcr Instance of |RttLcrInformation|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void setLcr(in int cmdId, in RttLcrInformation lcr);
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiRttControllerEventCallback.aidl b/wifi/aidl/android/hardware/wifi/IWifiRttControllerEventCallback.aidl
new file mode 100644
index 0000000..89f0ed8
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IWifiRttControllerEventCallback.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+import android.hardware.wifi.RttResult;
+
+/**
+ * RTT Response and Event Callbacks.
+ */
+@VintfStability
+oneway interface IWifiRttControllerEventCallback {
+    /**
+     * Invoked when an RTT result is available.
+     *
+     * @param cmdId Command Id corresponding to the original request.
+     * @param results Vector of |RttResult| instances.
+     */
+    void onResults(in int cmdId, in RttResult[] results);
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl b/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl
new file mode 100644
index 0000000..2dd57b2
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl
@@ -0,0 +1,555 @@
+/*
+ * 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;
+
+import android.hardware.wifi.IWifiStaIfaceEventCallback;
+import android.hardware.wifi.StaApfPacketFilterCapabilities;
+import android.hardware.wifi.StaBackgroundScanCapabilities;
+import android.hardware.wifi.StaBackgroundScanParameters;
+import android.hardware.wifi.StaLinkLayerStats;
+import android.hardware.wifi.StaRoamingCapabilities;
+import android.hardware.wifi.StaRoamingConfig;
+import android.hardware.wifi.StaRoamingState;
+import android.hardware.wifi.WifiBand;
+import android.hardware.wifi.WifiDebugRxPacketFateReport;
+import android.hardware.wifi.WifiDebugTxPacketFateReport;
+
+/**
+ * Interface used to represent a single STA iface.
+ */
+@VintfStability
+interface IWifiStaIface {
+    /**
+     * Mask of capabilities supported by this iface.
+     */
+    @VintfStability
+    @Backing(type="int")
+    enum StaIfaceCapabilityMask {
+        /**
+         * Support for APF APIs. APF (Android Packet Filter) is a
+         * BPF-like packet filtering bytecode executed by the firmware.
+         */
+        APF = 1 << 0,
+        /**
+         * Support for Background Scan APIs. Background scan allows the host
+         * to send a number of buckets down to the firmware. Each bucket
+         * contains a set of channels, a period, and some parameters about
+         * how and when to report results.
+         */
+        BACKGROUND_SCAN = 1 << 1,
+        /**
+         * Support for link layer stats APIs.
+         */
+        LINK_LAYER_STATS = 1 << 2,
+        /**
+         * Support for RSSI monitor APIs.
+         */
+        RSSI_MONITOR = 1 << 3,
+        /**
+         * Support for roaming APIs.
+         */
+        CONTROL_ROAMING = 1 << 4,
+        /**
+         * Support for Probe IE allow-listing.
+         */
+        PROBE_IE_ALLOWLIST = 1 << 5,
+        /**
+         * Support for MAC & Probe Sequence Number randomization.
+         */
+        SCAN_RAND = 1 << 6,
+        /**
+         * Support for 5 GHz Band.
+         */
+        STA_5G = 1 << 7,
+        /**
+         * Support for GAS/ANQP queries.
+         */
+        HOTSPOT = 1 << 8,
+        /**
+         * Support for Preferred Network Offload.
+         */
+        PNO = 1 << 9,
+        /**
+         * Support for Tunneled Direct Link Setup.
+         */
+        TDLS = 1 << 10,
+        /**
+         * Support for Tunneled Direct Link Setup off channel.
+         */
+        TDLS_OFFCHANNEL = 1 << 11,
+        /**
+         * Support for neighbour discovery offload.
+         */
+        ND_OFFLOAD = 1 << 12,
+        /**
+         * Support for keep alive packet offload.
+         */
+        KEEP_ALIVE = 1 << 13,
+        /**
+         * Support for tracking connection packets' fate.
+         */
+        DEBUG_PACKET_FATE = 1 << 14,
+    }
+
+    /**
+     * Get the name of this iface.
+     *
+     * @return Name of this iface.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|
+     */
+    String getName();
+
+    /**
+     * Configure roaming control parameters.
+     * Must fail if |StaIfaceCapabilityMask.CONTROL_ROAMING| is not set.
+     *
+     * @param config Instance of |StaRoamingConfig|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void configureRoaming(in StaRoamingConfig config);
+
+    /**
+     * Disable link layer stats collection.
+     * Must fail if |StaIfaceCapabilityMask.LINK_LAYER_STATS| is not set.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_STARTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void disableLinkLayerStatsCollection();
+
+    /**
+     * Enable link layer stats collection.
+     * Must fail if |StaIfaceCapabilityMask.LINK_LAYER_STATS| is not set.
+     *
+     * Radio statistics (once started) must not stop until disabled.
+     * Iface statistics (once started) reset and start afresh after each
+     * connection until disabled.
+     *
+     * @param debug true to enable field debug mode, false to disable. Driver
+     *        must collect all statistics regardless of performance impact.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void enableLinkLayerStatsCollection(in boolean debug);
+
+    /**
+     * Enable/Disable neighbour discovery offload functionality in the firmware.
+     *
+     * @param enable true to enable, false to disable.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void enableNdOffload(in boolean enable);
+
+    /**
+     * Used to query additional information about the chip's APF capabilities.
+     * Must fail if |StaIfaceCapabilityMask.APF| is not set.
+     *
+     * @return Instance of |StaApfPacketFilterCapabilities|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    StaApfPacketFilterCapabilities getApfPacketFilterCapabilities();
+
+    /**
+     * Used to query additional information about the chip's Background Scan capabilities.
+     * Must fail if |StaIfaceCapabilityMask.BACKGROUND_SCAN| is not set.
+     *
+     * @return Instance of |StaBackgroundScanCapabilities|
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    StaBackgroundScanCapabilities getBackgroundScanCapabilities();
+
+    /**
+     * Get the capabilities supported by this STA iface.
+     *
+     * @return Bitset of |StaIfaceCapabilityMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    StaIfaceCapabilityMask getCapabilities();
+
+    /**
+     * API to retrieve the fates of inbound packets.
+     * - HAL implementation must return the fates of
+     *   all the frames received for the most recent association.
+     *   The fate reports must follow the same order as their respective
+     *   packets.
+     * - HAL implementation may choose (but is not required) to include
+     *   reports for management frames.
+     * - Packets reported by firmware, but not recognized by driver,
+     *   must be included. However, the ordering of the corresponding
+     *   reports is at the discretion of HAL implementation.
+     * - Framework must be able to call this API multiple times for the same
+     *   association.
+     *
+     * @return Vector of |WifiDebugRxPacketFateReport| instances corresponding
+     *         to the packet fates.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_STARTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    WifiDebugRxPacketFateReport[] getDebugRxPacketFates();
+
+    /**
+     * API to retrieve fates of outbound packets.
+     * - HAL implementation must return the fates of
+     *   all the frames transmitted for the most recent association.
+     *   The fate reports must follow the same order as their respective
+     *   packets.
+     * - HAL implementation may choose (but is not required) to include
+     *   reports for management frames.
+     * - Packets reported by firmware, but not recognized by driver,
+     *   must be included. However, the ordering of the corresponding
+     *   reports is at the discretion of HAL implementation.
+     * - Framework must be able to call this API multiple times for the same
+     *   association.
+     *
+     * @return Vector of |WifiDebugTxPacketFateReport| instances corresponding
+     *         to the packet fates.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_STARTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    WifiDebugTxPacketFateReport[] getDebugTxPacketFates();
+
+    /**
+     * Gets the factory MAC address of the STA interface.
+     *
+     * @return Factory MAC address of the STA interface.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    byte[6] getFactoryMacAddress();
+
+    /**
+     * Retrieve the latest link layer stats.
+     * Must fail if |StaIfaceCapabilityMask.LINK_LAYER_STATS| is not set or if
+     * link layer stats collection hasn't been explicitly enabled.
+     *
+     * @return Instance of |LinkLayerStats|.
+     * @throws ServiceSpecificException with one of the following values:
+     *     |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *     |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *     |WifiStatusCode.ERROR_NOT_STARTED|,
+     *     |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *     |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    StaLinkLayerStats getLinkLayerStats();
+
+    /**
+     * Get roaming control capabilities.
+     * Must fail if |StaIfaceCapabilityMask.CONTROL_ROAMING| is not set.
+     *
+     * @return Instance of |StaRoamingCapabilities|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    StaRoamingCapabilities getRoamingCapabilities();
+
+    /**
+     * Used to query the list of valid frequencies (depending on the country
+     * code set) for the provided band. These channels may be specified in the
+     * |BackgroundScanBucketParameters.frequenciesInMhz| for a background scan
+     * request.
+     *
+     * @param band Band for which the frequency list is being generated.
+     * @return Vector of valid frequencies for the provided band.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    int[] getValidFrequenciesForBand(in WifiBand band);
+
+    /**
+     * Installs an APF program on this iface, replacing an existing
+     * program if present.
+     * Must fail if |StaIfaceCapabilityMask.APF| is not set.
+     *
+     * APF docs
+     * ==========================================================================
+     * APF functionality, instructions and bytecode/binary format is described in:
+     * http://android.googlesource.com/platform/hardware/google/apf/
+     * +/b75c9f3714cfae3dad3d976958e063150781437e/apf.h
+     *
+     * The interpreter API is described here:
+     * http://android.googlesource.com/platform/hardware/google/apf/+/
+     * b75c9f3714cfae3dad3d976958e063150781437e/apf_interpreter.h#32
+     *
+     * The assembler/generator API is described in javadocs here:
+     * http://android.googlesource.com/platform/frameworks/base/+/
+     * 4456f33a958a7f09e608399da83c4d12b2e7d191/services/net/java/android/net/
+     * apf/ApfGenerator.java
+     *
+     * Disassembler usage is described here:
+     * http://android.googlesource.com/platform/hardware/google/apf/+/
+     * b75c9f3714cfae3dad3d976958e063150781437e/apf_disassembler.c#65
+     *
+     * The BPF to APF translator usage is described here:
+     * http://android.googlesource.com/platform/frameworks/base/+/
+     * 4456f33a958a7f09e608399da83c4d12b2e7d191/tests/net/java/android/net/
+     * apf/Bpf2Apf.java
+     * ==========================================================================
+     *
+     * @param program APF Program to be set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void installApfPacketFilter(in byte[] program);
+
+    /**
+     * Fetches a consistent snapshot of the entire APF program and working
+     * memory buffer and returns it to the host. The returned buffer contains
+     * both code and data. Its length must match the most recently returned
+     * |StaApfPacketFilterCapabilities.maxLength|.
+     *
+     * While the snapshot is being fetched, the APF interpreter must not execute
+     * and all incoming packets must be passed to the host as if there was no
+     * APF program installed.
+     *
+     * Must fail with |WifiStatusCode.ERROR_NOT_SUPPORTED| if
+     * |StaIfaceCapabilityMask.APF| is not set.
+     *
+     * @return The entire APF working memory buffer when status is
+     *         |WifiStatusCode.SUCCESS|, empty otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     * @see getApfPacketFilterCapabilities()
+     * @see installApfPacketFilter()
+     */
+    byte[] readApfPacketFilterData();
+
+    /**
+     * Requests notifications of significant events on this iface. Multiple calls
+     * to this must register multiple callbacks, each of which must receive all
+     * events.
+     *
+     * @param callback An instance of the |IWifiStaIfaceEventCallback| AIDL
+     *        interface object.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|
+     */
+    void registerEventCallback(in IWifiStaIfaceEventCallback callback);
+
+    /**
+     * Changes the MAC address of the STA Interface to the given
+     * MAC address.
+     *
+     * @param mac MAC address to change to.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void setMacAddress(in byte[6] mac);
+
+    /**
+     * Set the roaming control state with the parameters configured
+     * using |configureRoaming|. Depending on the roaming state set, the
+     * driver/firmware would enable/disable control over roaming decisions.
+     * Must fail if |StaIfaceCapabilityMask.CONTROL_ROAMING| is not set.
+     *
+     * @param state State of the roaming control.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_BUSY|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void setRoamingState(in StaRoamingState state);
+
+    /**
+     * Turn on/off scan only mode for the interface.
+     *
+     * @param enable True to enable scan only mode, false to disable.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.FAILURE_UNKNOWN|
+     */
+    void setScanMode(in boolean enable);
+
+    /**
+     * Start a background scan using the given cmdId as an identifier. Only one
+     * active background scan need be supported.
+     * Must fail if |StaIfaceCapabilityMask.BACKGROUND_SCAN| is not set.
+     *
+     * When this is called all requested buckets must be scanned, starting the
+     * beginning of the cycle.
+     *
+     * For example:
+     * If there are two buckets specified
+     *  - Bucket 1: period=10s
+     *  - Bucket 2: period=20s
+     *  - Bucket 3: period=30s
+     * Then the following scans must occur
+     *  - t=0  buckets 1, 2, and 3 are scanned
+     *  - t=10 bucket 1 is scanned
+     *  - t=20 bucket 1 and 2 are scanned
+     *  - t=30 bucket 1 and 3 are scanned
+     *  - t=40 bucket 1 and 2 are scanned
+     *  - t=50 bucket 1 is scanned
+     *  - t=60 buckets 1, 2, and 3 are scanned
+     *  - and the pattern repeats
+     *
+     * If any scan does not occur or is incomplete (error, interrupted, etc),
+     * then a cached scan result must still be recorded with the
+     * WIFI_SCAN_FLAG_INTERRUPTED flag set.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param params Background scan parameters.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void startBackgroundScan(in int cmdId, in StaBackgroundScanParameters params);
+
+    /**
+     * API to start packet fate monitoring.
+     * - Once started, monitoring must remain active until HAL is stopped or the
+     *   chip is reconfigured.
+     * - When HAL is unloaded, all packet fate buffers must be cleared.
+     * - The packet fates are used to monitor the state of packets transmitted/
+     *   received during association.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void startDebugPacketFateMonitoring();
+
+    /**
+     * Start RSSI monitoring on the currently connected access point.
+     * Once the monitoring is enabled, the
+     * |IWifiStaIfaceEventCallback.onRssiThresholdBreached| callback must be
+     * invoked to indicate if the RSSI goes above |maxRssi| or below |minRssi|.
+     * Must fail if |StaIfaceCapabilityMask.RSSI_MONITOR| is not set.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param maxRssi Maximum RSSI threshold.
+     * @param minRssi Minimum RSSI threshold.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_ARGS_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void startRssiMonitoring(in int cmdId, in int maxRssi, in int minRssi);
+
+    /**
+     * Start sending the specified keep alive packets periodically.
+     *
+     * @param cmdId Command Id to use for this invocation.
+     * @param ipPacketData IP packet contents to be transmitted.
+     * @param etherType 16 bit ether type to be set in the ethernet frame
+     *        transmitted.
+     * @param srcAddress Source MAC address of the packet.
+     * @param dstAddress Destination MAC address of the packet.
+     * @param periodInMs Interval at which this packet must be transmitted.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void startSendingKeepAlivePackets(in int cmdId, in byte[] ipPacketData, in char etherType,
+            in byte[6] srcAddress, in byte[6] dstAddress, in int periodInMs);
+
+    /**
+     * Stop the current background scan.
+     * Must fail if |StaIfaceCapabilityMask.BACKGROUND_SCAN| is not set.
+     *
+     * @param cmdId Command Id corresponding to the request.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_STARTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void stopBackgroundScan(in int cmdId);
+
+    /**
+     * Stop RSSI monitoring.
+     * Must fail if |StaIfaceCapabilityMask.RSSI_MONITOR| is not set.
+     *
+     * @param cmdId Command Id corresponding to the request.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_STARTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void stopRssiMonitoring(in int cmdId);
+
+    /**
+     * Stop sending the specified keep alive packets.
+     *
+     * @param cmdId Command Id corresponding to the request.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    void stopSendingKeepAlivePackets(in int cmdId);
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl b/wifi/aidl/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl
new file mode 100644
index 0000000..93a255f
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IWifiStaIfaceEventCallback.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.wifi;
+
+import android.hardware.wifi.StaScanData;
+import android.hardware.wifi.StaScanResult;
+
+@VintfStability
+oneway interface IWifiStaIfaceEventCallback {
+    /**
+     * Called for each received beacon/probe response for a scan with the
+     * |REPORT_EVENTS_FULL_RESULTS| flag set in
+     * |StaBackgroundScanBucketParameters.eventReportScheme|.
+     *
+     * @param cmdId Command Id corresponding to the request.
+     * @param bucketsScanned Bitset where each bit indicates if the bucket with
+     *        that index (starting at 0) was scanned.
+     * @param result Full scan result for an AP.
+     */
+    void onBackgroundFullScanResult(in int cmdId, in int bucketsScanned, in StaScanResult result);
+
+    /**
+     * Callback indicating that an ongoing background scan request has failed.
+     * The background scan needs to be restarted to continue scanning.
+     *
+     * @param cmdId Command Id corresponding to the request.
+     */
+    void onBackgroundScanFailure(in int cmdId);
+
+    /**
+     * Called when the |StaBackgroundScanBucketParameters.eventReportScheme| flags
+     * for at least one bucket that was just scanned was
+     * |REPORT_EVENTS_EACH_SCAN|, or one of the configured thresholds was
+     * breached.
+     *
+     * @param cmdId Command Id corresponding to the request.
+     * @param scanDatas List of scan result for all AP's seen since last callback.
+     */
+    void onBackgroundScanResults(in int cmdId, in StaScanData[] scanDatas);
+
+    /**
+     * Called when the RSSI of the currently connected access point goes beyond the
+     * thresholds set via |IWifiStaIface.startRssiMonitoring|.
+     *
+     * @param cmdId Command Id corresponding to the request.
+     * @param currBssid BSSID of the currently connected access point.
+     * @param currRssi RSSI of the currently connected access point.
+     */
+    void onRssiThresholdBreached(in int cmdId, in byte[6] currBssid, in int currRssi);
+}
diff --git a/wifi/aidl/android/hardware/wifi/IfaceConcurrencyType.aidl b/wifi/aidl/android/hardware/wifi/IfaceConcurrencyType.aidl
new file mode 100644
index 0000000..26c183c
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IfaceConcurrencyType.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+/**
+ * List of interface concurrency types, used in reporting device concurrency capabilities.
+ */
+@VintfStability
+@Backing(type="int")
+enum IfaceConcurrencyType {
+    /**
+     * Concurrency type for station mode.
+     */
+    STA,
+    /**
+     * Concurrency type of single-port AP mode.
+     */
+    AP,
+    /**
+     * Concurrency type of two-port bridged AP mode.
+     */
+    AP_BRIDGED,
+    /**
+     * Concurrency type of peer-to-peer mode.
+     */
+    P2P,
+    /**
+     * Concurrency type of neighborhood area network mode.
+     */
+    NAN_IFACE,
+}
diff --git a/wifi/aidl/android/hardware/wifi/IfaceType.aidl b/wifi/aidl/android/hardware/wifi/IfaceType.aidl
new file mode 100644
index 0000000..c89d94b
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/IfaceType.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * List of supported interface types.
+ */
+@VintfStability
+@Backing(type="int")
+enum IfaceType {
+    STA,
+    AP,
+    P2P,
+    /**
+     * NAN control interface. Datapath support must be queried and created
+     * through this interface. Declared as 'NAN_IFACE' instead of 'NAN'
+     * because the compiler complains that NAN is already defined by math.h
+     */
+    NAN_IFACE,
+}
diff --git a/wifi/aidl/android/hardware/wifi/MacAddress.aidl b/wifi/aidl/android/hardware/wifi/MacAddress.aidl
new file mode 100644
index 0000000..d59dfe3
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/MacAddress.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+/**
+ * Byte array representing a Mac Address. Use when we need to
+ * pass an array of Mac Addresses to a method, as variable-sized
+ * 2D arrays are not supported in AIDL.
+ *
+ * TODO (b/210705533): Replace this type with a 2D byte array.
+ */
+@VintfStability
+parcelable MacAddress {
+    byte[6] data;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanBandIndex.aidl b/wifi/aidl/android/hardware/wifi/NanBandIndex.aidl
new file mode 100644
index 0000000..5da5869
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanBandIndex.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+/**
+ * The discovery bands supported by NAN.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanBandIndex {
+    NAN_BAND_24GHZ = 0,
+    NAN_BAND_5GHZ,
+    /**
+     * Index for 6 GHz band.
+     */
+    NAN_BAND_6GHZ = 2,
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanBandSpecificConfig.aidl b/wifi/aidl/android/hardware/wifi/NanBandSpecificConfig.aidl
new file mode 100644
index 0000000..2e13486
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanBandSpecificConfig.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.wifi;
+
+/**
+ * NAN band-specific configuration.
+ */
+@VintfStability
+parcelable NanBandSpecificConfig {
+    /**
+     * RSSI values controlling clustering behavior per spec. RSSI values are specified without a
+     * sign, e.g. a value of -65dBm would be specified as 65.
+     */
+    byte rssiClose;
+    byte rssiMiddle;
+    /**
+     * RSSI value determining whether discovery is near (used if enabled in discovery by
+     * |NanDiscoveryCommonConfig.useRssiThreshold|).
+     * RSSI values are specified without a sign, e.g. a value of -65dBm would be specified as 65.
+     * NAN Spec: RSSI_close_proximity
+     */
+    byte rssiCloseProximity;
+    /**
+     * Dwell time of each discovery channel in milliseconds. If set to 0, then the firmware
+     * determines the dwell time to use.
+     */
+    char dwellTimeMs;
+    /**
+     * Scan period of each discovery channel in seconds. If set to 0, then the firmware determines
+     * the scan period to use.
+     */
+    char scanPeriodSec;
+    /**
+     * Specifies the discovery window interval for Sync beacons and SDF's.
+     * Valid values of DW Interval are: 1, 2, 3, 4 and 5 corresponding to 1, 2, 4, 8, and 16 DWs.
+     * Value of 0:
+     *  - reserved in 2.4GHz band
+     *  - no wakeup at all in 5GHz band
+     * The publish/subscribe period values don't override the device level configurations if
+     * they are specified.
+     * Configuration is only used only if |validDiscoveryWindowIntervalVal| is set to true.
+     * NAN Spec: Device Capability Attribute / 2.4 GHz DW, Device Capability Attribute / 5 GHz DW
+     */
+    boolean validDiscoveryWindowIntervalVal;
+    byte discoveryWindowIntervalVal;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanCapabilities.aidl b/wifi/aidl/android/hardware/wifi/NanCapabilities.aidl
new file mode 100644
index 0000000..6042a05
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanCapabilities.aidl
@@ -0,0 +1,88 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanCipherSuiteType;
+
+/**
+ * NDP Capabilities response.
+ */
+@VintfStability
+parcelable NanCapabilities {
+    /**
+     * Maximum number of clusters which the device can join concurrently.
+     */
+    int maxConcurrentClusters;
+    /**
+     * Maximum number of concurrent publish discovery sessions.
+     */
+    int maxPublishes;
+    /**
+     * Maximum number of concurrent subscribe discovery sessions.
+     */
+    int maxSubscribes;
+    /**
+     * Maximum length (in bytes) of service name.
+     */
+    int maxServiceNameLen;
+    /**
+     * Maximum length (in bytes) of individual match filters.
+     */
+    int maxMatchFilterLen;
+    /**
+     * Maximum length (in bytes) of aggregate match filters across all active sessions.
+     */
+    int maxTotalMatchFilterLen;
+    /**
+     * Maximum length (in bytes) of the service specific info field.
+     */
+    int maxServiceSpecificInfoLen;
+    /**
+     * Maximum length (in bytes) of the extended service specific info field.
+     */
+    int maxExtendedServiceSpecificInfoLen;
+    /**
+     * Maximum number of data interfaces (NDI) which can be created concurrently on the device.
+     */
+    int maxNdiInterfaces;
+    /**
+     * Maximum number of data paths (NDP) which can be created concurrently on the device, across
+     * all data interfaces (NDI).
+     */
+    int maxNdpSessions;
+    /**
+     * Maximum length (in bytes) of application info field (used in data-path negotiations).
+     */
+    int maxAppInfoLen;
+    /**
+     * Maximum number of transmitted followup messages which can be queued by the firmware.
+     */
+    int maxQueuedTransmitFollowupMsgs;
+    /**
+     * Maximum number MAC interface addresses which can be specified to a subscribe discovery
+     * session.
+     */
+    int maxSubscribeInterfaceAddresses;
+    /**
+     * The set of supported Cipher suites. The |NanCipherSuiteType| bit fields are used.
+     */
+    NanCipherSuiteType supportedCipherSuites;
+    /**
+     * Flag to indicate id instant communication mode is supported.
+     */
+    boolean instantCommunicationModeSupportFlag;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanCipherSuiteType.aidl b/wifi/aidl/android/hardware/wifi/NanCipherSuiteType.aidl
new file mode 100644
index 0000000..9e3d684
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanCipherSuiteType.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+/**
+ * Cipher suite flags.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanCipherSuiteType {
+    NONE = 0,
+    SHARED_KEY_128_MASK = 1 << 0,
+    SHARED_KEY_256_MASK = 1 << 1,
+    /**
+     *  NCS-PK-128
+     */
+    PUBLIC_KEY_128_MASK = 1 << 2,
+    /**
+     *  NCS-PK-256
+     */
+    PUBLIC_KEY_256_MASK = 1 << 3,
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanClusterEventInd.aidl b/wifi/aidl/android/hardware/wifi/NanClusterEventInd.aidl
new file mode 100644
index 0000000..76a3034
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanClusterEventInd.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanClusterEventType;
+
+/**
+ * Cluster event indication structure. Triggered on events impacting how this device is
+ * visible to peers - cluster forming, joining a new cluster, or changing of the MAC address.
+ */
+@VintfStability
+parcelable NanClusterEventInd {
+    /**
+     * Event type causing the cluster event indication to be triggered.
+     */
+    NanClusterEventType eventType;
+    /**
+     * MAC Address associated with the corresponding event.
+     */
+    byte[6] addr;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanClusterEventType.aidl b/wifi/aidl/android/hardware/wifi/NanClusterEventType.aidl
new file mode 100644
index 0000000..c07bf17
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanClusterEventType.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Event types for a cluster event indication.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanClusterEventType {
+    /**
+     * Management/discovery interface MAC address has changed
+     * (e.g. due to randomization or at startup).
+     */
+    DISCOVERY_MAC_ADDRESS_CHANGED = 0,
+    /**
+     * A new cluster has been formed by this device.
+     */
+    STARTED_CLUSTER,
+    /**
+     * This device has joined an existing cluster.
+     */
+    JOINED_CLUSTER,
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanConfigRequest.aidl b/wifi/aidl/android/hardware/wifi/NanConfigRequest.aidl
new file mode 100644
index 0000000..82a7b6e
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanConfigRequest.aidl
@@ -0,0 +1,82 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanBandSpecificConfig;
+
+/**
+ * Configuration parameters of NAN. Used when enabling and re-configuring a NAN cluster.
+ */
+@VintfStability
+parcelable NanConfigRequest {
+    /**
+     * Master preference of this device.
+     * NAN Spec: Master Indication Attribute / Master Preference
+     */
+    byte masterPref;
+    /**
+     * Controls whether or not the |IWifiNanIfaceEventCallback.eventClusterEvent| will be delivered
+     * for |NanClusterEventType.DISCOVERY_MAC_ADDRESS_CHANGED|.
+     */
+    boolean disableDiscoveryAddressChangeIndication;
+    /**
+     * Controls whether or not the |IWifiNanIfaceEventCallback.eventClusterEvent| will be delivered
+     * for |NanClusterEventType.STARTED_CLUSTER|.
+     */
+    boolean disableStartedClusterIndication;
+    /**
+     * Controls whether or not the |IWifiNanIfaceEventCallback.eventClusterEvent| will be delivered
+     * for |NanClusterEventType.JOINED_CLUSTER|.
+     */
+    boolean disableJoinedClusterIndication;
+    /**
+     * Control whether publish service IDs are included in Sync/Discovery beacons.
+     * NAN Spec: Service ID List Attribute
+     */
+    boolean includePublishServiceIdsInBeacon;
+    /**
+     * If |includePublishServiceIdsInBeacon| is true, then specifies the number of publish service
+     * IDs to include in the Sync/Discovery beacons. Value = 0: include as many service IDs as will
+     * fit into the maximum allowed beacon frame size. Value must fit within 7 bits - i.e. <= 127.
+     */
+    byte numberOfPublishServiceIdsInBeacon;
+    /**
+     * Control whether subscribe service IDs are included in Sync/Discovery beacons.
+     * Spec: Subscribe Service ID List Attribute
+     */
+    boolean includeSubscribeServiceIdsInBeacon;
+    /**
+     * If |includeSubscribeServiceIdsInBeacon| is true, then specifies the number of subscribe
+     * service IDs to include in the Sync/Discovery beacons. Value = 0: include as many service IDs
+     * as will fit into the maximum allowed beacon frame size. Value must fit within 7 bits - i.e.
+     * <= 127.
+     */
+    byte numberOfSubscribeServiceIdsInBeacon;
+    /**
+     * Number of samples used to calculate RSSI.
+     */
+    char rssiWindowSize;
+    /**
+     * Specifies the interval in seconds that the NAN management interface MAC address is
+     * randomized. A value of 0 is used to disable the MAC address randomization.
+     */
+    int macAddressRandomizationIntervalSec;
+    /**
+     * Additional configuration provided per band. Indexed by |NanBandIndex|.
+     */
+    NanBandSpecificConfig[3] bandSpecificConfig;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanConfigRequestSupplemental.aidl b/wifi/aidl/android/hardware/wifi/NanConfigRequestSupplemental.aidl
new file mode 100644
index 0000000..eb01a9f
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanConfigRequestSupplemental.aidl
@@ -0,0 +1,63 @@
+/*
+ * 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;
+
+/**
+ * Additional NAN configuration request parameters.
+ */
+@VintfStability
+parcelable NanConfigRequestSupplemental {
+    /**
+     * Specify the Discovery Beacon interval in ms. Specification only applicable if the device
+     * transmits Discovery Beacons (based on the Wi-Fi Aware protocol selection criteria). The value
+     * can be increased to reduce power consumption (on devices which would transmit Discovery
+     * Beacons). However, cluster synchronization time will likely increase.
+     * Values are:
+     *  - A value of 0 indicates that the HAL sets the interval to a default (implementation
+     * specific).
+     *  - A positive value.
+     */
+    int discoveryBeaconIntervalMs;
+    /**
+     * The number of spatial streams to be used for transmitting NAN management frames (does NOT
+     * apply to data-path packets). A small value may reduce power consumption for small discovery
+     * packets. Values are:
+     *  - A value of 0 indicates that the HAL sets the number to a default (implementation
+     * specific).
+     *  - A positive value.
+     */
+    int numberOfSpatialStreamsInDiscovery;
+    /**
+     * Controls whether the device may terminate listening on a Discovery Window (DW) earlier than
+     * the DW termination (16ms) if no information is received. Enabling the feature will result in
+     * lower power consumption, but may result in some missed messages and hence increased latency.
+     */
+    boolean enableDiscoveryWindowEarlyTermination;
+    /**
+     * Controls whether NAN RTT (ranging) is permitted. Global flag on any NAN RTT operations are
+     * allowed. Controls ranging in the context of discovery as well as direct RTT.
+     */
+    boolean enableRanging;
+    /**
+     * Controls whether NAN instant communication mode is enabled.
+     */
+    boolean enableInstantCommunicationMode;
+    /**
+     * Controls which channel NAN instant communication mode operates on.
+     */
+    int instantModeChannel;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanDataPathChannelCfg.aidl b/wifi/aidl/android/hardware/wifi/NanDataPathChannelCfg.aidl
new file mode 100644
index 0000000..3aaea40
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanDataPathChannelCfg.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+/**
+ * NAN DP (data-path) channel config options.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanDataPathChannelCfg {
+    CHANNEL_NOT_REQUESTED = 0,
+    REQUEST_CHANNEL_SETUP,
+    FORCE_CHANNEL_SETUP,
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanDataPathChannelInfo.aidl b/wifi/aidl/android/hardware/wifi/NanDataPathChannelInfo.aidl
new file mode 100644
index 0000000..e5c3538
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanDataPathChannelInfo.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiChannelWidthInMhz;
+
+/**
+ * NAN data path channel information provided to the framework.
+ */
+@VintfStability
+parcelable NanDataPathChannelInfo {
+    /**
+     * Channel frequency in MHz.
+     */
+    int channelFreq;
+    /**
+     * Channel bandwidth in MHz.
+     */
+    WifiChannelWidthInMhz channelBandwidth;
+    /**
+     * Number of spatial streams used in the channel.
+     */
+    int numSpatialStreams;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanDataPathConfirmInd.aidl b/wifi/aidl/android/hardware/wifi/NanDataPathConfirmInd.aidl
new file mode 100644
index 0000000..621f036
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanDataPathConfirmInd.aidl
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanDataPathChannelInfo;
+import android.hardware.wifi.NanStatus;
+
+/**
+ * NAN Data path confirmation indication structure. Event indication is
+ * received on both initiator and responder side when negotiation for a
+ * data-path finishes on success or failure.
+ */
+@VintfStability
+parcelable NanDataPathConfirmInd {
+    /**
+     * ID of the data-path.
+     */
+    int ndpInstanceId;
+    /**
+     * Indicates whether the data-path setup succeeded (true) or failed (false).
+     */
+    boolean dataPathSetupSuccess;
+    /**
+     * MAC address of the peer's data-interface (not its management/discovery interface).
+     */
+    byte[6] peerNdiMacAddr;
+    /**
+     * Arbitrary information communicated from the peer as part of the data-path setup process -
+     * there is no semantic meaning to these bytes. They are passed-through from sender to receiver
+     * as-is with no parsing. Max length: |NanCapabilities.maxAppInfoLen|. NAN Spec: Data Path
+     * Attributes / NDP Attribute / NDP Specific Info
+     */
+    byte[] appInfo;
+    /**
+     * Failure reason if |dataPathSetupSuccess| is false.
+     */
+    NanStatus status;
+    /**
+     * The channel(s) on which the NDP is scheduled to operate.
+     * Updates to the operational channels are provided using the |eventDataPathScheduleUpdate|
+     * event.
+     */
+    NanDataPathChannelInfo[] channelInfo;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanDataPathRequestInd.aidl b/wifi/aidl/android/hardware/wifi/NanDataPathRequestInd.aidl
new file mode 100644
index 0000000..de9ee32
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanDataPathRequestInd.aidl
@@ -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.
+ */
+
+package android.hardware.wifi;
+
+/**
+ * NAN Data path request indication message structure.
+ * Event indication received by an intended Responder when a NAN
+ * data request initiated by an Initiator.
+ */
+@VintfStability
+parcelable NanDataPathRequestInd {
+    /**
+     * ID of an active publish or subscribe discovery session. The data-path
+     * request is in the context of this discovery session.
+     * NAN Spec: Data Path Attributes / NDP Attribute / Publish ID
+     */
+    byte discoverySessionId;
+    /**
+     * MAC address of the Initiator peer. This is the MAC address of the peer's
+     * management/discovery NAN interface.
+     */
+    byte[6] peerDiscMacAddr;
+    /**
+     * ID of the data-path. Used to identify the data-path in further negotiation/APIs.
+     */
+    int ndpInstanceId;
+    /**
+     * Specifies whether or not security is required by the peer for the data-path being created.
+     * NAN Spec: Data Path Attributes / NDP Attribute / NDP Control / Security Present
+     */
+    boolean securityRequired;
+    /**
+     * Arbitrary information communicated from the peer as part of the data-path setup process.
+     * Therer is no semantic meaning to these bytes. They are passed-through from sender to
+     * receiver as-is with no parsing.
+     * Max length: |NanCapabilities.maxAppInfoLen|.
+     * NAN Spec: Data Path Attributes / NDP Attribute / NDP Specific Info
+     */
+    byte[] appInfo;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanDataPathScheduleUpdateInd.aidl b/wifi/aidl/android/hardware/wifi/NanDataPathScheduleUpdateInd.aidl
new file mode 100644
index 0000000..0f41d8f
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanDataPathScheduleUpdateInd.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanDataPathChannelInfo;
+
+/**
+ * NAN data path channel information update indication structure.
+ * Event indication is received by all NDP owners whenever the channels on
+ * which the NDP operates are updated.
+ * Note: Multiple NDPs may share the same schedule. The indication specifies
+ * all NDPs to which it applies.
+ */
+@VintfStability
+parcelable NanDataPathScheduleUpdateInd {
+    /**
+     * The discovery address (NMI) of the peer to which the NDP is connected.
+     */
+    byte[6] peerDiscoveryAddress;
+    /**
+     * The updated channel(s) information.
+     */
+    NanDataPathChannelInfo[] channelInfo;
+    /**
+     * The list of NDPs to which this update applies.
+     */
+    int[] ndpInstanceIds;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanDataPathSecurityConfig.aidl b/wifi/aidl/android/hardware/wifi/NanDataPathSecurityConfig.aidl
new file mode 100644
index 0000000..42a5616
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanDataPathSecurityConfig.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.wifi;
+
+import android.hardware.wifi.NanCipherSuiteType;
+import android.hardware.wifi.NanDataPathSecurityType;
+
+/**
+ * Configuration of NAN data-path security.
+ */
+@VintfStability
+parcelable NanDataPathSecurityConfig {
+    /**
+     * Security configuration of the data-path (NDP). Security is enabled if not equal to
+     * |NanDataPathSecurityType.OPEN|.
+     * NAN Spec: Service Discovery Extension Attribute (SDEA) / Control / Security Required
+     */
+    NanDataPathSecurityType securityType;
+    /**
+     * Cipher type for data-paths. If |securityType| is |NanDataPathSecurityType.OPEN| then must
+     * be set to |NanCipherSuiteType.NONE|. Otherwise a non-|NanCipherSuiteType.NONE| cipher suite
+     * must be specified.
+     */
+    NanCipherSuiteType cipherType;
+    /**
+     * Optional Pairwise Master Key (PMK). Must be specified (and is only used) if |securityType| is
+     * set to |NanDataPathSecurityType.PMK|.
+     * Ref: IEEE 802.11i
+     */
+    byte[32] pmk;
+    /**
+     * Optional Passphrase. Must be specified (and is only used) if |securityType| is set to
+     * |NanDataPathSecurityType.PASSPHRASE|.
+     * Min length: |IWifiNanIface.MIN_DATA_PATH_CONFIG_PASSPHRASE_LENGTH|
+     * Max length: |IWifiNanIface.MAX_DATA_PATH_CONFIG_PASSPHRASE_LENGTH|
+     * NAN Spec: Appendix: Mapping passphrase to PMK for NCS-SK Cipher Suites
+     */
+    byte[] passphrase;
+    /**
+     * Security Context Identifier attribute contains PMKID. Shall be included in NDP setup and
+     * response messages. Security Context Identifier identifies the Security Context. When
+     * security is enabled this field contains the 16 octet PMKID identifying the PMK used for
+     * setting up the Secure Data Path.
+     */
+    byte[16] scid;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanDataPathSecurityType.aidl b/wifi/aidl/android/hardware/wifi/NanDataPathSecurityType.aidl
new file mode 100644
index 0000000..da23ffa
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanDataPathSecurityType.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+/**
+ * NAN DP (data-path) security configuration options.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanDataPathSecurityType {
+    OPEN,
+    PMK,
+    PASSPHRASE,
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanDebugConfig.aidl b/wifi/aidl/android/hardware/wifi/NanDebugConfig.aidl
new file mode 100644
index 0000000..d8fab0d
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanDebugConfig.aidl
@@ -0,0 +1,80 @@
+/*
+ * 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;
+
+/**
+ * Debug configuration parameters. Many of these allow non-standard-compliant operation and are
+ * not intended for normal operational mode.
+ */
+@VintfStability
+parcelable NanDebugConfig {
+    /**
+     * Specification of the lower 2 bytes of the cluster ID. The cluster ID is 50-60-9a-01-00-00 to
+     * 50-60-9a-01-FF-FF. Configuration is of the bottom and top values of the range (which default
+     * to 0x0000 and 0xFFFF respectively).
+     * Configuration is only used if |validClusterIdVals| is set to true.
+     */
+    boolean validClusterIdVals;
+    char clusterIdBottomRangeVal;
+    char clusterIdTopRangeVal;
+    /**
+     * NAN management interface address. If specified (|validIntfAddrVal| is true), then overrides
+     * any other configuration (specifically the default randomization configured by
+     * |NanConfigRequest.macAddressRandomizationIntervalSec|).
+     */
+    boolean validIntfAddrVal;
+    byte[6] intfAddrVal;
+    /**
+     * Combination of the 24 bit Organizationally Unique ID (OUI) and the 8 bit OUI type.
+     * Used if |validOuiVal| is set to true.
+     */
+    boolean validOuiVal;
+    int ouiVal;
+    /**
+     * Force the Random Factor to the specified value for all transmitted Sync/Discovery beacons.
+     * Used if |validRandomFactorForceVal| is set to true.
+     * NAN Spec: Master Indication Attribute / Random Factor
+     */
+    boolean validRandomFactorForceVal;
+    byte randomFactorForceVal;
+    /**
+     * Forces the hop-count for all transmitted Sync and Discovery Beacons NO matter the real
+     * hop-count being received over the air. Used if the |validHopCountForceVal| flag is set to
+     * true.
+     * NAN Spec: Cluster Attribute / Anchor Master Information / Hop Count to Anchor Master
+     */
+    boolean validHopCountForceVal;
+    byte hopCountForceVal;
+    /**
+     * Frequency in MHz to of the discovery channel in the specified band. Indexed by
+     * |NanBandIndex|. Used if the |validDiscoveryChannelVal| is set to true.
+     */
+    boolean validDiscoveryChannelVal;
+    int[3] discoveryChannelMhzVal;
+    /**
+     * Specifies whether sync/discovery beacons are transmitted in the specified band. Indexed by
+     * |NanBandIndex|. Used if the |validUseBeaconsInBandVal| is set to true.
+     */
+    boolean validUseBeaconsInBandVal;
+    boolean[3] useBeaconsInBandVal;
+    /**
+     * Specifies whether SDF (service discovery frames) are transmitted in the specified band.
+     * Indexed by |NanBandIndex|. Used if the |validUseSdfInBandVal| is set to true.
+     */
+    boolean validUseSdfInBandVal;
+    boolean[3] useSdfInBandVal;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl b/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl
new file mode 100644
index 0000000..ca1e016
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanDiscoveryCommonConfig.aidl
@@ -0,0 +1,158 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanDataPathSecurityConfig;
+import android.hardware.wifi.NanMatchAlg;
+import android.hardware.wifi.NanRangingIndication;
+
+/**
+ * Configurations of NAN discovery sessions. Common to publish and subscribe discovery.
+ */
+@VintfStability
+parcelable NanDiscoveryCommonConfig {
+    /**
+     * The ID of the discovery session being configured. A value of 0 specifies a request to create
+     * a new discovery session. The new discovery session ID is returned with
+     * |IWifiNanIfaceEventCallback.notifyStartPublishResponse| or
+     * |IWifiNanIfaceEventCallback.notifyStartSubscribeResponse|.
+     * NAN Spec: Service Descriptor Attribute (SDA) / Instance ID
+     */
+    byte sessionId;
+    /**
+     * The lifetime of the discovery session in seconds. A value of 0 means run forever or until
+     * canceled using |IWifiIface.stopPublishRequest| or |IWifiIface.stopSubscribeRequest|.
+     */
+    char ttlSec;
+    /**
+     * Indicates the interval between two Discovery Windows in which the device supporting the
+     * service is awake to transmit or receive the Service Discovery frames. Valid values of Awake
+     * DW Interval are: 1, 2, 4, 8 and 16. A value of 0 will default to 1. Does not override
+     * |NanBandSpecificConfig.discoveryWindowIntervalVal| configurations if those are specified.
+     */
+    char discoveryWindowPeriod;
+    /**
+     * The lifetime of the discovery session in number of transmitted SDF discovery packets. A value
+     * of 0 means forever or until canceled using |IWifiIface.stopPublishRequest| or
+     * |IWifiIface.stopSubscribeRequest|.
+     */
+    byte discoveryCount;
+    /**
+     * UTF-8 encoded string identifying the service.
+     * Max length: |NanCapabilities.maxServiceNameLen|.
+     * NAN Spec: The only acceptable single-byte UTF-8 symbols for a Service Name are alphanumeric
+     * values (A-Z, a-z, 0-9), the hyphen ('-'), and the period ('.'). All valid multi-byte UTF-8
+     * characters are acceptable in a Service Name.
+     */
+    byte[] serviceName;
+    /**
+     * Specifies how often to trigger |IWifiNanIfaceEventCallback.eventMatch| when continuously
+     * discovering the same discovery session (with no changes).
+     */
+    NanMatchAlg discoveryMatchIndicator;
+    /**
+     * Arbitrary information communicated in discovery packets - there is no semantic meaning to
+     * these bytes. They are passed-through from publisher to subscriber as-is with no parsing. Max
+     * length: |NanCapabilities.maxServiceSpecificInfoLen|. NAN Spec: Service Descriptor Attribute
+     * (SDA) / Service Info
+     */
+    byte[] serviceSpecificInfo;
+    /**
+     * Arbitrary information communicated in discovery packets - there is no semantic meaning to
+     * these bytes. They are passed-through from publisher to subscriber as-is with no parsing. Max
+     * length: |NanCapabilities.maxExtendedServiceSpecificInfoLen|. Spec: Service Descriptor
+     * Extension Attribute (SDEA) / Service Info
+     */
+    byte[] extendedServiceSpecificInfo;
+    /**
+     * Ordered sequence of <length, value> pairs (|length| uses 1 byte and contains the number of
+     * bytes in the |value| field) which specify further match criteria (beyond the service name).
+     * The match behavior is specified in details in the NAN spec.
+     * Publisher: used in SOLICITED or SOLICITED_UNSOLICITED sessions.
+     * Subscriber: used in ACTIVE or PASSIVE sessions.
+     * Max length: |NanCapabilities.maxMatchFilterLen|.
+     * NAN Spec: matching_filter_rx
+     */
+    byte[] rxMatchFilter;
+    /**
+     * Ordered sequence of <length, value> pairs (|length| uses 1 byte and contains the number of
+     * bytes in the |value| field) which specify further match criteria (beyond the service name).
+     * The match behavior is specified in details in the NAN spec.
+     * Publisher: used if provided.
+     * Subscriber: used (if provided) only in ACTIVE sessions.
+     * Max length: |NanCapabilities.maxMatchFilterLen|.
+     * NAN Spec: matching_filter_tx and Service Descriptor Attribute (SDA) / Matching Filter
+     */
+    byte[] txMatchFilter;
+    /**
+     * Specifies whether or not the discovery session uses the
+     * |NanBandSpecificConfig.rssiCloseProximity| value (configured in enable/configure requests) to
+     * filter out matched discovered peers.
+     * NAN Spec: Service Descriptor Attribute / Service Control / Discovery Range Limited.
+     */
+    boolean useRssiThreshold;
+    /**
+     * Controls whether or not the |IWifiNanIfaceEventCallback.eventPublishTerminated| (for publish
+     * discovery sessions) or |IWifiNanIfaceEventCallback.eventSubscribeTerminated| (for subscribe
+     * discovery sessions) will be delivered.
+     */
+    boolean disableDiscoveryTerminationIndication;
+    /**
+     * Controls whether or not |IWifiNanIfaceEventCallback.eventMatchExpired| will be delivered.
+     */
+    boolean disableMatchExpirationIndication;
+    /**
+     * Controls whether or not |IWifiNanIfaceEventCallback.eventFollowupReceived| will be delivered.
+     */
+    boolean disableFollowupReceivedIndication;
+    /**
+     * Security configuration of data-paths created in the context of this discovery session.
+     * Security parameters can be overridden during the actual construction of the data-path -
+     * allowing individual data-paths to have unique PMKs or passphrases.
+     */
+    NanDataPathSecurityConfig securityConfig;
+    /**
+     * Specifies whether or not there is a ranging requirement in this discovery session.
+     * Ranging is only performed if all other match criteria with the peer are met. Ranging must
+     * be performed if both peers in the discovery session (publisher and subscriber) set this
+     * flag to true. Otherwise, if either peer sets this flag to false, ranging must not be
+     * performed and must not impact discovery decisions. Note: Specifying that ranging is required
+     * also implies that this device must automatically accept ranging requests from peers. NAN
+     * Spec: Service Discovery Extension Attribute (SDEA) / Control / Ranging Require.
+     */
+    boolean rangingRequired;
+    /**
+     * Interval in ms between two ranging measurements. Only relevant if |rangingRequired| is true.
+     * If the Awake DW interval specified either in |discoveryWindowPeriod| or in
+     * |NanBandSpecificConfig.discoveryWindowIntervalVal| is larger than the ranging interval then
+     * priority is given to Awake DW interval.
+     */
+    int rangingIntervalMs;
+    /**
+     * The type of ranging feedback to be provided by discovery session matches
+     * |IWifiNanIfaceEventCallback.eventMatch|. Only relevant if |rangingRequired| is true.
+     */
+    NanRangingIndication configRangingIndications;
+    /**
+     * The ingress and egress distance in cm. If ranging is enabled (|rangingEnabled| is true) then
+     * |configRangingIndications| is used to determine whether ingress and/or egress (or neither)
+     * are used to determine whether a match has occurred.
+     * NAN Spec: Service Discovery Extension Attribute (SDEA) / Ingress & Egress Range Limit
+     */
+    char distanceIngressCm;
+    char distanceEgressCm;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanEnableRequest.aidl b/wifi/aidl/android/hardware/wifi/NanEnableRequest.aidl
new file mode 100644
index 0000000..8c28fe1
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanEnableRequest.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanConfigRequest;
+import android.hardware.wifi.NanDebugConfig;
+
+/**
+ * Enable requests for NAN. Start-up configuration for |IWifiNanIface.enableRequest|.
+ */
+@VintfStability
+parcelable NanEnableRequest {
+    /**
+     * Enable operation in a specific band. Indexed by |NanBandIndex|.
+     */
+    boolean[3] operateInBand;
+    /**
+     * Specify extent of cluster by specifying the max hop count.
+     */
+    byte hopCountMax;
+    /**
+     * Configurations of NAN cluster operation. Can also be modified at run-time using
+     * |IWifiNanIface.configRequest|.
+     */
+    NanConfigRequest configParams;
+    /**
+     * Non-standard configurations of NAN cluster operation. Useful for debugging operations.
+     */
+    NanDebugConfig debugConfigs;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanFollowupReceivedInd.aidl b/wifi/aidl/android/hardware/wifi/NanFollowupReceivedInd.aidl
new file mode 100644
index 0000000..20bc9b1
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanFollowupReceivedInd.aidl
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+/**
+ * Follow up message received from peer indication structure.
+ */
+@VintfStability
+parcelable NanFollowupReceivedInd {
+    /**
+     * Discovery session (publish or subscribe) ID of a previously created discovery session. The
+     * message is received in the context of this discovery session.
+     * NAN Spec: Service Descriptor Attribute (SDA) / Instance ID
+     */
+    byte discoverySessionId;
+    /**
+     * A unique ID of the peer. Can be subsequently used in |IWifiNanIface.transmitFollowupRequest|
+     * or to set up a data-path.
+     */
+    int peerId;
+    /**
+     * The NAN Discovery (management) MAC address of the peer.
+     */
+    byte[6] addr;
+    /**
+     * Indicates whether received in a further availability window (FAW) if true, or in a discovery
+     * window (DW) if false.
+     */
+    boolean receivedInFaw;
+    /**
+     * Received message from the peer. There is no semantic meaning to these bytes. They are
+     * passed-through from sender to receiver as-is with no parsing.
+     * Max length: |NanCapabilities.maxServiceSpecificInfoLen|.
+     * NAN Spec: Service Descriptor Attribute (SDA) / Service Info
+     */
+    byte[] serviceSpecificInfo;
+    /**
+     * Arbitrary information communicated in discovery packets. There is no semantic meaning to
+     * these bytes. They are passed-through from publisher to subscriber as-is with no parsing. Max
+     * length: |NanCapabilities.maxExtendedServiceSpecificInfoLen|. Spec: Service Descriptor
+     * Extension Attribute (SDEA) / Service Info
+     */
+    byte[] extendedServiceSpecificInfo;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanInitiateDataPathRequest.aidl b/wifi/aidl/android/hardware/wifi/NanInitiateDataPathRequest.aidl
new file mode 100644
index 0000000..264a873
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanInitiateDataPathRequest.aidl
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanDataPathChannelCfg;
+import android.hardware.wifi.NanDataPathSecurityConfig;
+
+/**
+ *  Data Path Initiator requesting a data-path.
+ */
+@VintfStability
+parcelable NanInitiateDataPathRequest {
+    /**
+     * ID of the peer. Obtained as part of an earlier |IWifiNanIfaceEventCallback.eventMatch| or
+     * |IWifiNanIfaceEventCallback.eventFollowupReceived|.
+     */
+    int peerId;
+    /**
+     * NAN management interface MAC address of the peer. Obtained as part of an earlier
+     * |IWifiNanIfaceEventCallback.eventMatch| or
+     * |IWifiNanIfaceEventCallback.eventFollowupReceived|.
+     */
+    byte[6] peerDiscMacAddr;
+    /**
+     * Config flag for channel request.
+     */
+    NanDataPathChannelCfg channelRequestType;
+    /**
+     * Channel frequency in MHz to start data-path. Not relevant if |channelRequestType| is
+     * |NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED|.
+     */
+    int channel;
+    /**
+     * NAN data interface name on which this data-path session is to be initiated.
+     * This must be an interface created using |IWifiNanIface.createDataInterfaceRequest|.
+     */
+    String ifaceName;
+    /**
+     * Security configuration of the requested data-path.
+     */
+    NanDataPathSecurityConfig securityConfig;
+    /**
+     * Arbitrary information communicated to the peer as part of the data-path setup process. There
+     * is no semantic meaning to these bytes. They are passed-through from sender to receiver as-is
+     * with no parsing.
+     * Max length: |NanCapabilities.maxAppInfoLen|.
+     * NAN Spec: Data Path Attributes / NDP Attribute / NDP Specific Info
+     */
+    byte[] appInfo;
+    /**
+     * A service name to be used with |passphrase| to construct a Pairwise Master Key (PMK) for the
+     * data-path. Only relevant when a data-path is requested which is not associated with a NAN
+     * discovery session - e.g. using out-of-band discovery.
+     * Constraints: same as |NanDiscoveryCommonConfig.serviceName|
+     * NAN Spec: Appendix: Mapping pass-phrase to PMK for NCS-SK Cipher Suites
+     */
+    byte[] serviceNameOutOfBand;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanMatchAlg.aidl b/wifi/aidl/android/hardware/wifi/NanMatchAlg.aidl
new file mode 100644
index 0000000..dc96a47
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanMatchAlg.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ * NAN Match indication type. Controls how often to trigger |IWifiNanIfaceEventCallback.eventMatch|
+ * for a single discovery session - i.e. continuously discovering the same publisher with no new
+ * data.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanMatchAlg {
+    MATCH_ONCE = 0,
+    MATCH_CONTINUOUS,
+    MATCH_NEVER,
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanMatchInd.aidl b/wifi/aidl/android/hardware/wifi/NanMatchInd.aidl
new file mode 100644
index 0000000..896cde0
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanMatchInd.aidl
@@ -0,0 +1,129 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanCipherSuiteType;
+import android.hardware.wifi.NanRangingIndication;
+
+/**
+ * Match indication structure.
+ */
+@VintfStability
+parcelable NanMatchInd {
+    /**
+     * Publish or subscribe discovery session ID of an existing discovery session.
+     * NAN Spec: Service Descriptor Attribute (SDA) / Instance ID
+     */
+    byte discoverySessionId;
+    /**
+     * A unique ID of the peer. Can be subsequently used in |IWifiNanIface.transmitFollowupRequest|
+     * or to set up a data-path.
+     */
+    int peerId;
+    /**
+     * The NAN Discovery (management) MAC address of the peer.
+     */
+    byte[6] addr;
+    /**
+     * The arbitrary information contained in the |NanDiscoveryCommonConfig.serviceSpecificInfo| of
+     * the peer's discovery session configuration.
+     * Max length: |NanCapabilities.maxServiceSpecificInfoLen|.
+     * NAN Spec: Service Descriptor Attribute (SDA) / Service Info
+     */
+    byte[] serviceSpecificInfo;
+    /**
+     * Arbitrary information communicated in discovery packets. There is no semantic meaning to
+     * these bytes. They are passed-through from publisher to subscriber as-is with no parsing. Max
+     * length: |NanCapabilities.maxExtendedServiceSpecificInfoLen|. Spec: Service Descriptor
+     * Extension Attribute (SDEA) / Service Info
+     */
+    byte[] extendedServiceSpecificInfo;
+    /**
+     * The match filter from the discovery packet (publish or subscribe) which caused service
+     * discovery. Matches the |NanDiscoveryCommonConfig.txMatchFilter| of the peer's Unsolicited
+     * publish message or of the local device's Active subscribe message.
+     * Max length: |NanCapabilities.maxMatchFilterLen|.
+     * NAN Spec: Service Descriptor Attribute (SDA) / Matching Filter
+     */
+    byte[] matchFilter;
+    /**
+     * Indicates the type of discovery: true if match occurred on a Beacon frame, false if the match
+     * occurred on a Service Discovery Frame (SDF).
+     */
+    boolean matchOccurredInBeaconFlag;
+    /**
+     * Flag to indicate firmware is out of resources and that it can no longer track this Service
+     * Name. Indicates that while |IWifiNanIfaceEventCallback.eventMatch| will be received, the
+     * |NanDiscoveryCommonConfig.discoveryMatchIndicator| configuration will not be honored.
+     */
+    boolean outOfResourceFlag;
+    /**
+     * If RSSI filtering was enabled using |NanDiscoveryCommonConfig.useRssiThreshold| in discovery
+     * session setup, then this field contains the received RSSI value. It will contain 0 if RSSI
+     * filtering was not enabled.
+     * RSSI values are returned without sign, e.g. -70dBm will be returned as 70.
+     */
+    byte rssiValue;
+    /**
+     * Cipher type for data-paths constructed in the context of this discovery session. Valid if
+     * |peerRequiresSecurityEnabledInNdp| is true.
+     */
+    NanCipherSuiteType peerCipherType;
+    /**
+     * Indicates whether or not the peer requires security enabled in any data-path (NDP)
+     * constructed in the context of this discovery session. The |cipherType| specifies the cipher
+     * type for such data-paths. NAN Spec: Service Discovery Extension Attribute (SDEA) / Control /
+     * Security Required
+     */
+    boolean peerRequiresSecurityEnabledInNdp;
+    /**
+     * Indicates whether or not the peer requires (and hence allows) ranging in the context of this
+     * discovery session.
+     * Note that ranging is only performed if all other match criteria with the peer are met.
+     * NAN Spec: Service Discovery Extension Attribute (SDEA) / Control / Ranging Require.
+     */
+    boolean peerRequiresRanging;
+    /**
+     * Ranging indication supersedes the NanMatchAlg specification.
+     * Ex: If NanMatchAlg is MATCH_ONCE, but ranging indication is continuous, then continuous
+     * match notifications will be received (with ranging information).
+     * Ranging indication data is provided if Ranging required is enabled in the discovery
+     * specification and:
+     *   1) continuous ranging is specified.
+     *   2) ingress/egress is specified and:
+     *       - notify once for ingress >= ingress_distance and egress <= egress_distance,
+     *       - same for ingress_egress_both
+     * If the Awake DW intervals are larger than the ranging intervals, then priority is given
+     * to the device DW intervals.
+     *
+     * If ranging was required and executed, this contains the distance to the peer in mm. The
+     * |rangingIndicationType| field specifies the event which triggered ranging.
+     */
+    int rangingMeasurementInMm;
+    /**
+     * The ranging event(s) which triggered the ranging. e.g. can indicate that continuous ranging
+     * was requested, or else that an ingress event occurred.
+     */
+    NanRangingIndication rangingIndicationType;
+    /**
+     * Security Context Identifier attribute contains PMKID. Shall be included in NDP setup and
+     * response messages. Security Context Identifie identifies the Security Context. For NAN
+     * Shared Key Cipher Suite, this field contains the 16 octet PMKID identifying the PMK used for
+     * setting up the Secure Data Path.
+     */
+    byte[] scid;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl b/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl
new file mode 100644
index 0000000..6dd079c
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanPublishRequest.aidl
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanDiscoveryCommonConfig;
+import android.hardware.wifi.NanPublishType;
+import android.hardware.wifi.NanTxType;
+
+/**
+ * Publish request. Specifies a publish discovery operation.
+ */
+@VintfStability
+parcelable NanPublishRequest {
+    /**
+     * Common configuration of discovery sessions.
+     */
+    NanDiscoveryCommonConfig baseConfigs;
+    /**
+     * Type of the publish discovery session.
+     */
+    NanPublishType publishType;
+    /**
+     * For publishType of |NanPublishType.SOLICITED| or |NanPublishType.UNSOLICITED_SOLICITED|,
+     * this specifies the type of transmission used for responding to the probing subscribe
+     * discovery peer.
+     */
+    NanTxType txType;
+    /**
+     * Specifies whether data-path requests |IWifiNanIfaceEventCallback.eventDataPathRequest| (in
+     * the context of this discovery session) are automatically accepted (if true) - in which case
+     * the Responder must not call the |IWifiNanIface.respondToDataPathIndicationRequest| method and
+     * the device must automatically accept the data-path request and complete the negotiation.
+     */
+    boolean autoAcceptDataPathRequests;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanPublishType.aidl b/wifi/aidl/android/hardware/wifi/NanPublishType.aidl
new file mode 100644
index 0000000..a7a1c48
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanPublishType.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+/**
+ * NAN publish discovery session types.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanPublishType {
+    UNSOLICITED = 0,
+    SOLICITED,
+    UNSOLICITED_SOLICITED,
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanRangingIndication.aidl b/wifi/aidl/android/hardware/wifi/NanRangingIndication.aidl
new file mode 100644
index 0000000..731cbfc
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanRangingIndication.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+/**
+ * Ranging in the context of discovery session indication controls. Controls
+ * the frequency of ranging-driven |IWifiNanIfaceEventCallback.eventMatch|.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanRangingIndication {
+    CONTINUOUS_INDICATION_MASK = 1 << 0,
+    INGRESS_MET_MASK = 1 << 1,
+    EGRESS_MET_MASK = 1 << 2,
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanRespondToDataPathIndicationRequest.aidl b/wifi/aidl/android/hardware/wifi/NanRespondToDataPathIndicationRequest.aidl
new file mode 100644
index 0000000..6960e71
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanRespondToDataPathIndicationRequest.aidl
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanDataPathSecurityConfig;
+
+/**
+ * Response to a data-path request from a peer.
+ */
+@VintfStability
+parcelable NanRespondToDataPathIndicationRequest {
+    /**
+     * Accept (true) or reject (false) the request.
+     * NAN Spec: Data Path Attributes / NDP Attribute / Type and Status
+     */
+    boolean acceptRequest;
+    /**
+     * ID of the data-path (NDP) for which we're responding. Obtained as part of the request in
+     * |IWifiNanIfaceEventCallback.eventDataPathRequest|.
+     */
+    int ndpInstanceId;
+    /**
+     * NAN data interface name on which this data-path session is to be started.
+     * This must be an interface created using |IWifiNanIface.createDataInterfaceRequest|.
+     */
+    String ifaceName;
+    /**
+     * Security configuration of the requested data-path.
+     */
+    NanDataPathSecurityConfig securityConfig;
+    /**
+     * Arbitrary information communicated to the peer as part of the data-path setup process. There
+     * is no semantic meaning to these bytes. They are passed-through from sender to receiver as-is
+     * with no parsing.
+     * Max length: |NanCapabilities.maxAppInfoLen|.
+     * NAN Spec: Data Path Attributes / NDP Attribute / NDP Specific Info
+     */
+    byte[] appInfo;
+    /**
+     * A service name to be used with |passphrase| to construct a Pairwise Master Key (PMK) for the
+     * data-path. Only relevant when a data-path is requested which is not associated with a NAN
+     * discovery session - e.g. using out-of-band discovery.
+     * Constraints: same as |NanDiscoveryCommonConfig.serviceName|
+     * NAN Spec: Appendix: Mapping pass-phrase to PMK for NCS-SK Cipher Suites
+     */
+    byte[] serviceNameOutOfBand;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanSrfType.aidl b/wifi/aidl/android/hardware/wifi/NanSrfType.aidl
new file mode 100644
index 0000000..4063b17
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanSrfType.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+/**
+ * NAN Service Response Filter Attribute Bit.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanSrfType {
+    BLOOM_FILTER = 0,
+    PARTIAL_MAC_ADDR,
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanStatus.aidl b/wifi/aidl/android/hardware/wifi/NanStatus.aidl
new file mode 100644
index 0000000..ad29e5b6
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanStatus.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+import android.hardware.wifi.NanStatusCode;
+
+/**
+ * Status information returned in NAN notifications.
+ */
+@VintfStability
+parcelable NanStatus {
+    /**
+     * Status of the command request.
+     */
+    NanStatusCode status;
+    /**
+     * Further description of the issue causing a failure.
+     */
+    String description;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanStatusCode.aidl b/wifi/aidl/android/hardware/wifi/NanStatusCode.aidl
new file mode 100644
index 0000000..d63a50e
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanStatusCode.aidl
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+/**
+ * NAN API response codes used in request notifications and events.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanStatusCode {
+    SUCCESS = 0,
+    /**
+     * NAN Discovery Engine/Host driver failures.
+     */
+    INTERNAL_FAILURE = 1,
+    /**
+     * NAN OTA failures.
+     */
+    PROTOCOL_FAILURE = 2,
+    /**
+     * The publish/subscribe discovery session id is invalid.
+     */
+    INVALID_SESSION_ID = 3,
+    /**
+     * Out of resources to fufill request.
+     */
+    NO_RESOURCES_AVAILABLE = 4,
+    /**
+     * Invalid arguments passed.
+     */
+    INVALID_ARGS = 5,
+    /**
+     * Invalid peer id.
+     */
+    INVALID_PEER_ID = 6,
+    /**
+     * Invalid NAN data-path (ndp) id.
+     */
+    INVALID_NDP_ID = 7,
+    /**
+     * Attempting to enable NAN when not available, e.g. wifi is disabled.
+     */
+    NAN_NOT_ALLOWED = 8,
+    /**
+     * Over the air ACK not received.
+     */
+    NO_OTA_ACK = 9,
+    /**
+     * Attempting to enable NAN when already enabled.
+     */
+    ALREADY_ENABLED = 10,
+    /**
+     * Can't queue tx followup message for transmission.
+     */
+    FOLLOWUP_TX_QUEUE_FULL = 11,
+    /**
+     * Unsupported concurrency of NAN and another feature - NAN disabled.
+     */
+    UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 12,
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanSubscribeRequest.aidl b/wifi/aidl/android/hardware/wifi/NanSubscribeRequest.aidl
new file mode 100644
index 0000000..12c1170
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanSubscribeRequest.aidl
@@ -0,0 +1,70 @@
+/*
+ * 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;
+
+import android.hardware.wifi.MacAddress;
+import android.hardware.wifi.NanDiscoveryCommonConfig;
+import android.hardware.wifi.NanSrfType;
+import android.hardware.wifi.NanSubscribeType;
+
+/**
+ * Subscribe request. Specifies a subscribe discovery operation.
+ */
+@VintfStability
+parcelable NanSubscribeRequest {
+    /**
+     * Common configuration of discovery sessions.
+     */
+    NanDiscoveryCommonConfig baseConfigs;
+    /**
+     * The type of the subscribe discovery session.
+     */
+    NanSubscribeType subscribeType;
+    /**
+     * For |NanSubscribeType.ACTIVE| subscribe discovery sessions, specifies how the Service
+     * Response Filter (SRF) attribute is populated. Relevant only if |shouldUseSrf| is set to true.
+     * NAN Spec: Service Descriptor Attribute (SDA) / Service Response Filter / SRF Control / SRF
+     * Type
+     */
+    NanSrfType srfType;
+    /**
+     * Configure whether inclusion of an address in |intfAddr| indicates that those devices should
+     * respond or the reverse. Relevant only if |shouldUseSrf| is set to true and |srfType| is set
+     * to |NanSrfType.PARTIAL_MAC_ADDR|. NAN Spec: Service Descriptor Attribute (SDA) / Service
+     * Response Filter / SRF Control / Include
+     */
+    boolean srfRespondIfInAddressSet;
+    /**
+     * Control whether the Service Response Filter (SRF) is used.
+     * NAN Spec: Service Descriptor Attribute (SDA) / Service Control /
+     *           Service Response Filter Present
+     */
+    boolean shouldUseSrf;
+    /**
+     * Control whether the presence of |NanDiscoveryCommonConfig.serviceSpecificInfo| data is needed
+     * in the publisher in order to trigger service discovery, i.e. a
+     * |IWifiNanIfaceEventCallback.eventMatch|. The test is for presence of data - not for the
+     * specific contents of the data.
+     */
+    boolean isSsiRequiredForMatch;
+    /**
+     * NAN Interface Addresses constituting the Service Response Filter (SRF).
+     * Max length (number of addresses): |NanCapabilities.maxSubscribeInterfaceAddresses|.
+     * NAN Spec: Service Descriptor Attribute (SDA) / Service Response Filter / Address Set
+     */
+    MacAddress[] intfAddr;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanSubscribeType.aidl b/wifi/aidl/android/hardware/wifi/NanSubscribeType.aidl
new file mode 100644
index 0000000..a5e8182
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanSubscribeType.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+/**
+ * NAN subscribe discovery session types.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanSubscribeType {
+    PASSIVE = 0,
+    ACTIVE,
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanTransmitFollowupRequest.aidl b/wifi/aidl/android/hardware/wifi/NanTransmitFollowupRequest.aidl
new file mode 100644
index 0000000..c88b4ff
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanTransmitFollowupRequest.aidl
@@ -0,0 +1,69 @@
+/*
+ * 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;
+
+/**
+ * Transmit follow up message request.
+ */
+@VintfStability
+parcelable NanTransmitFollowupRequest {
+    /**
+     * ID of an active publish or subscribe discovery session. Follow-up message is transmitted in
+     * the context of the discovery session. NAN Spec: Service Descriptor Attribute (SDA) / Instance
+     * ID
+     */
+    byte discoverySessionId;
+    /**
+     * ID of the peer. Obtained as part of an earlier |IWifiNanIfaceEventCallback.eventMatch| or
+     * |IWifiNanIfaceEventCallback.eventFollowupReceived|.
+     */
+    int peerId;
+    /**
+     * MAC address of the peer. Obtained as part of an earlier
+     * |IWifiNanIfaceEventCallback.eventMatch| or
+     * |IWifiNanIfaceEventCallback.eventFollowupReceived|.
+     */
+    byte[6] addr;
+    /**
+     * Whether the follow-up message should be transmitted with a high priority.
+     */
+    boolean isHighPriority;
+    /**
+     * Whether the follow-up message should be transmitted in a discovery window (true) or a further
+     * availability window (false).
+     */
+    boolean shouldUseDiscoveryWindow;
+    /**
+     * Arbitrary information communicated to the peer. There is no semantic meaning to these
+     * bytes. They are passed-through from sender to receiver as-is with no parsing.
+     * Max length: |NanCapabilities.maxServiceSpecificInfoLen|.
+     * NAN Spec: Service Descriptor Attribute (SDA) / Service Info
+     */
+    byte[] serviceSpecificInfo;
+    /**
+     * Arbitrary information communicated in discovery packets. There is no semantic meaning to
+     * these bytes. They are passed-through from publisher to subscriber as-is with no parsing. Max
+     * length: |NanCapabilities.maxExtendedServiceSpecificInfoLen|. Spec: Service Descriptor
+     * Extension Attribute (SDEA) / Service Info
+     */
+    byte[] extendedServiceSpecificInfo;
+    /**
+     * Disable |IWifiNanIfaceEventCallback.eventTransmitFollowup| - i.e. do not get indication on
+     * whether the follow-up was transmitted and received successfully.
+     */
+    boolean disableFollowupResultIndication;
+}
diff --git a/wifi/aidl/android/hardware/wifi/NanTxType.aidl b/wifi/aidl/android/hardware/wifi/NanTxType.aidl
new file mode 100644
index 0000000..904a7f4
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/NanTxType.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+/**
+ * NAN transmit type used in |NanPublishType.SOLICITED| or |NanPublishType.UNSOLICITED_SOLICITED|
+ * publish discovery sessions. Describes the addressing of the packet responding to an ACTIVE
+ * subscribe query.
+ */
+@VintfStability
+@Backing(type="int")
+enum NanTxType {
+    BROADCAST = 0,
+    UNICAST,
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttBw.aidl b/wifi/aidl/android/hardware/wifi/RttBw.aidl
new file mode 100644
index 0000000..9d42dc0
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttBw.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.wifi;
+
+/**
+ * RTT Measurement Bandwidth.
+ */
+@VintfStability
+@Backing(type="int")
+enum RttBw {
+    BW_5MHZ = 0x01,
+    BW_10MHZ = 0x02,
+    BW_20MHZ = 0x04,
+    BW_40MHZ = 0x08,
+    BW_80MHZ = 0x10,
+    BW_160MHZ = 0x20,
+    BW_320MHZ = 0x40,
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl b/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl
new file mode 100644
index 0000000..7c47ed5
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+import android.hardware.wifi.RttBw;
+import android.hardware.wifi.RttPreamble;
+
+/**
+ * RTT Capabilities.
+ */
+@VintfStability
+parcelable RttCapabilities {
+    /**
+     * Whether 1-sided rtt data collection is supported.
+     */
+    boolean rttOneSidedSupported;
+    /**
+     * Whether ftm rtt data collection is supported.
+     */
+    boolean rttFtmSupported;
+    /**
+     * Whether initiator supports LCI request. Applies to 2-sided RTT.
+     */
+    boolean lciSupported;
+    /**
+     * Whether initiator supports LCR request. Applies to 2-sided RTT.
+     */
+    boolean lcrSupported;
+    /**
+     * Whether 11mc responder mode is supported.
+     */
+    boolean responderSupported;
+    /**
+     * Bit mask indicating what preamble is supported by initiator.
+     * Combination of |RttPreamble| values.
+     */
+    RttPreamble preambleSupport;
+    /**
+     * Bit mask indicating what BW is supported by initiator.
+     * Combination of |RttBw| values.
+     */
+    RttBw bwSupport;
+    /**
+     * Draft 11mc spec version supported by chip.
+     * For instance, version 4.0 must be 40 and version 4.3 must be 43 etc.
+     */
+    byte mcVersion;
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttConfig.aidl b/wifi/aidl/android/hardware/wifi/RttConfig.aidl
new file mode 100644
index 0000000..fc2c2e0
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttConfig.aidl
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import android.hardware.wifi.RttBw;
+import android.hardware.wifi.RttPeerType;
+import android.hardware.wifi.RttPreamble;
+import android.hardware.wifi.RttType;
+import android.hardware.wifi.WifiChannelInfo;
+
+/**
+ * RTT configuration.
+ */
+@VintfStability
+parcelable RttConfig {
+    /**
+     * Peer device mac address.
+     */
+    byte[6] addr;
+    /**
+     * 1-sided or 2-sided RTT.
+     */
+    RttType type;
+    /**
+     * Optional peer device hint (STA, P2P, AP).
+     */
+    RttPeerType peer;
+    /**
+     * Required for STA-AP mode, optional for P2P, NBD etc.
+     */
+    WifiChannelInfo channel;
+    /**
+     * Time interval between bursts (units: 100 ms).
+     * Applies to 1-sided and 2-sided RTT multi-burst requests.
+     * Range: 0-31, 0: no preference by initiator (2-sided RTT).
+     */
+    int burstPeriod;
+    /**
+     * Total number of RTT bursts to be executed. Will be
+     * specified in the same way as the parameter "Number of
+     * Burst Exponent" found in the FTM frame format. This
+     * applies to both 1-sided RTT and 2-sided RTT. Valid
+     * values are 0 to 15 as defined in 802.11mc std.
+     * 0 means single shot.
+     * The implication of this parameter on the maximum
+     * number of RTT results is the following:
+     * for 1-sided RTT: max num of RTT results = (2^num_burst)*(num_frames_per_burst)
+     * for 2-sided RTT: max num of RTT results = (2^num_burst)*(num_frames_per_burst - 1)
+     */
+    int numBurst;
+    /**
+     * Number of frames per burst.
+     * Minimum value = 1, Maximum value = 31
+     * For 2-sided, this equals the number of FTM frames
+     * to be attempted in a single burst. This also
+     * equals the number of FTM frames that the
+     * initiator will request that the responder sends
+     * in a single frame.
+     */
+    int numFramesPerBurst;
+    /**
+     * Number of retries for a failed RTT frame.
+     * Applies to 1-sided RTT only. Minimum value = 0, Maximum value = 3
+     */
+    int numRetriesPerRttFrame;
+    /**
+     * The following fields are only valid for 2-side RTT.
+     *
+     *
+     * Maximum number of retries that the initiator can
+     * retry an FTMR frame.
+     * Minimum value = 0, Maximum value = 3
+     */
+    int numRetriesPerFtmr;
+    /**
+     * Whether to request location civic info or not.
+     */
+    boolean mustRequestLci;
+    /**
+     * Whether to request location civic records or not.
+     */
+    boolean mustRequestLcr;
+    /**
+     * Applies to 1-sided and 2-sided RTT. Valid values will
+     * be 2-11 and 15 as specified by the 802.11mc std for
+     * the FTM parameter burst duration. In a multi-burst
+     * request, if responder overrides with larger value,
+     * the initiator will return failure. In a single-burst
+     * request, if responder overrides with larger value,
+     * the initiator will send TMR_STOP to terminate RTT
+     * at the end of the burst_duration it requested.
+     */
+    int burstDuration;
+    /**
+     * RTT preamble to be used in the RTT frames.
+     */
+    RttPreamble preamble;
+    /**
+     * RTT BW to be used in the RTT frames.
+     */
+    RttBw bw;
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttLciInformation.aidl b/wifi/aidl/android/hardware/wifi/RttLciInformation.aidl
new file mode 100644
index 0000000..5a49de5
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttLciInformation.aidl
@@ -0,0 +1,69 @@
+/*
+ * 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;
+
+import android.hardware.wifi.RttMotionPattern;
+
+/**
+ * Movement pattern unknown.
+ */
+@VintfStability
+parcelable RttLciInformation {
+    /**
+     * Latitude in degrees * 2^25 , 2's complement.
+     */
+    long latitude;
+    /**
+     * Longitude in degrees * 2^25 , 2's complement.
+     */
+    long longitude;
+    /**
+     * Altitude in units of 1/256 m.
+     */
+    int altitude;
+    /**
+     * As defined in Section 2.3.2 of IETF RFC 6225.
+     */
+    byte latitudeUnc;
+    /**
+     * As defined in Section 2.3.2 of IETF RFC 6225.
+     */
+    byte longitudeUnc;
+    /**
+     * As defined in Section 2.4.5 from IETF RFC 6225.
+     */
+    byte altitudeUnc;
+    /**
+     * The following elements are for configuring the Z subelement.
+     *
+     *
+     * Motion pattern type.
+     */
+    RttMotionPattern motionPattern;
+    /**
+     * Floor in units of 1/16th of floor. 0x80000000 if unknown.
+     */
+    int floor;
+    /**
+     * In units of 1/64 m.
+     */
+    int heightAboveFloor;
+    /**
+     * In units of 1/64 m. 0 if unknown.
+     */
+    int heightUnc;
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttLcrInformation.aidl b/wifi/aidl/android/hardware/wifi/RttLcrInformation.aidl
new file mode 100644
index 0000000..b3bb13a
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttLcrInformation.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+@VintfStability
+parcelable RttLcrInformation {
+    /**
+     * Country code symbol.
+     */
+    byte[2] countryCode;
+    /**
+     * Civic info to be copied in FTM frame.
+     */
+    String civicInfo;
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttMotionPattern.aidl b/wifi/aidl/android/hardware/wifi/RttMotionPattern.aidl
new file mode 100644
index 0000000..00517ac
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttMotionPattern.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+@VintfStability
+@Backing(type="int")
+enum RttMotionPattern {
+    /**
+     * Not expected to change location.
+     */
+    NOT_EXPECTED = 0,
+    /**
+     * Expected to change location.
+     */
+    EXPECTED = 1,
+    /**
+     * Movement pattern unknown.
+     */
+    UNKNOWN = 2,
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttPeerType.aidl b/wifi/aidl/android/hardware/wifi/RttPeerType.aidl
new file mode 100644
index 0000000..148a8cc
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttPeerType.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ * RTT peer types.
+ */
+@VintfStability
+@Backing(type="int")
+enum RttPeerType {
+    AP = 1,
+    STA = 2,
+    P2P_GO = 3,
+    P2P_CLIENT = 4,
+    NAN_TYPE = 5,
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttPreamble.aidl b/wifi/aidl/android/hardware/wifi/RttPreamble.aidl
new file mode 100644
index 0000000..e460a94
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttPreamble.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+/**
+ * RTT Measurement Preamble.
+ */
+@VintfStability
+@Backing(type="int")
+enum RttPreamble {
+    LEGACY = 0x1,
+    HT = 0x2,
+    VHT = 0x4,
+    /**
+     * Preamble type for 11ax
+     */
+    HE = 0x8,
+    /**
+     * Preamble type for 11be
+     */
+    EHT = 0x10,
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttResponder.aidl b/wifi/aidl/android/hardware/wifi/RttResponder.aidl
new file mode 100644
index 0000000..a16f274
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttResponder.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+import android.hardware.wifi.RttPreamble;
+import android.hardware.wifi.WifiChannelInfo;
+
+/**
+ * RTT Responder information.
+ */
+@VintfStability
+parcelable RttResponder {
+    WifiChannelInfo channel;
+    RttPreamble preamble;
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttResult.aidl b/wifi/aidl/android/hardware/wifi/RttResult.aidl
new file mode 100644
index 0000000..565cce7
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttResult.aidl
@@ -0,0 +1,135 @@
+/*
+ * 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;
+
+import android.hardware.wifi.RttStatus;
+import android.hardware.wifi.RttType;
+import android.hardware.wifi.WifiInformationElement;
+import android.hardware.wifi.WifiRateInfo;
+
+/**
+ * RTT results.
+ */
+@VintfStability
+parcelable RttResult {
+    /**
+     * Peer device mac address.
+     */
+    byte[6] addr;
+    /**
+     * Burst number in a multi-burst request.
+     */
+    int burstNum;
+    /**
+     * Total RTT measurement frames attempted.
+     */
+    int measurementNumber;
+    /**
+     * Total successful RTT measurement frames.
+     */
+    int successNumber;
+    /**
+     * Maximum number of "FTM frames per burst" supported by
+     * the responder STA. Applies to 2-sided RTT only.
+     * If reponder overrides with larger value:
+     * - for single-burst request, initiator will truncate the
+     * larger value and send a TMR_STOP after receiving as
+     * many frames as originally requested.
+     * - for multi-burst request, initiator will return
+     * failure right away.
+     */
+    byte numberPerBurstPeer;
+    /**
+     * Ranging status.
+     */
+    RttStatus status;
+    /**
+     * If status is RTT_STATUS_FAIL_BUSY_TRY_LATER,
+     * this will be the time provided by the responder as to
+     * when the request can be tried again. Applies to 2-sided
+     * RTT only. In sec, 1-31 sec.
+     */
+    byte retryAfterDuration;
+    /**
+     * RTT type.
+     */
+    RttType type;
+    /**
+     * Average rssi in 0.5 dB steps (e.g. 143 implies -71.5 dB).
+     */
+    int rssi;
+    /**
+     * Rssi spread in 0.5 dB steps (e.g. 5 implies 2.5 dB spread) - optional.
+     */
+    int rssiSpread;
+    /**
+     * 1-sided RTT: TX rate of RTT frame.
+     * 2-sided RTT: TX rate of initiator's Ack in response to FTM frame.
+     */
+    WifiRateInfo txRate;
+    /**
+     * 1-sided RTT: TX rate of Ack from other side.
+     * 2-sided RTT: TX rate of FTM frame coming from responder.
+     */
+    WifiRateInfo rxRate;
+    /**
+     * Round trip time in picoseconds.
+     */
+    long rtt;
+    /**
+     * Rtt standard deviation in picoseconds.
+     */
+    long rttSd;
+    /**
+     * Difference between max and min rtt times recorded in picoseconds.
+     */
+    long rttSpread;
+    /**
+     * Distance in mm (optional).
+     */
+    int distanceInMm;
+    /**
+     * Standard deviation in mm (optional).
+     */
+    int distanceSdInMm;
+    /**
+     * Difference between max and min distance recorded in mm (optional).
+     */
+    int distanceSpreadInMm;
+    /**
+     * Time of the measurement (in microseconds since boot).
+     */
+    long timeStampInUs;
+    /**
+     * Actual time taken by the FW to finish one burst
+     * measurement (in ms). Applies to 1-sided and 2-sided RTT.
+     */
+    int burstDurationInMs;
+    /**
+     * Number of bursts allowed by the responder. Applies
+     * to 2-sided RTT only.
+     */
+    int negotiatedBurstNum;
+    /**
+     * For 11mc only.
+     */
+    WifiInformationElement lci;
+    /**
+     * For 11mc only.
+     */
+    WifiInformationElement lcr;
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttStatus.aidl b/wifi/aidl/android/hardware/wifi/RttStatus.aidl
new file mode 100644
index 0000000..600165c
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttStatus.aidl
@@ -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.
+ */
+
+package android.hardware.wifi;
+
+/**
+ * Ranging status.
+ */
+@VintfStability
+@Backing(type="int")
+enum RttStatus {
+    SUCCESS = 0,
+    /**
+     * General failure status.
+     */
+    FAILURE = 1,
+    /**
+     * Target STA does not respond to request.
+     */
+    FAIL_NO_RSP = 2,
+    /**
+     * Request rejected. Applies to 2-sided RTT only.
+     */
+    FAIL_REJECTED = 3,
+    FAIL_NOT_SCHEDULED_YET = 4,
+    /**
+     * Timing measurement times out.
+     */
+    FAIL_TM_TIMEOUT = 5,
+    /**
+     * Target on different channel, cannot range.
+     */
+    FAIL_AP_ON_DIFF_CHANNEL = 6,
+    /**
+     * Ranging not supported.
+     */
+    FAIL_NO_CAPABILITY = 7,
+    /**
+     * Request aborted for an unknown reason.
+     */
+    ABORTED = 8,
+    /**
+     * Invalid T1-T4 timestamp.
+     */
+    FAIL_INVALID_TS = 9,
+    /**
+     * 11mc protocol failed.
+     */
+    FAIL_PROTOCOL = 10,
+    /**
+     * Request could not be scheduled.
+     */
+    FAIL_SCHEDULE = 11,
+    /**
+     * Responder cannot collaborate at time of request.
+     */
+    FAIL_BUSY_TRY_LATER = 12,
+    /**
+     * Bad request args.
+     */
+    INVALID_REQ = 13,
+    /**
+     * WiFi not enabled.
+     */
+    NO_WIFI = 14,
+    /**
+     * Responder overrides param info, cannot range with new params.
+     */
+    FAIL_FTM_PARAM_OVERRIDE = 15,
+    /**
+     * NAN ranging negotiation failure.
+     */
+    NAN_RANGING_PROTOCOL_FAILURE = 16,
+    /**
+     * NAN concurrency not supported (NDP + RTT).
+     */
+    NAN_RANGING_CONCURRENCY_NOT_SUPPORTED = 17,
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttType.aidl b/wifi/aidl/android/hardware/wifi/RttType.aidl
new file mode 100644
index 0000000..e95a928
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttType.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+/**
+ * RTT Types.
+ */
+@VintfStability
+@Backing(type="int")
+enum RttType {
+    ONE_SIDED = 1,
+    TWO_SIDED = 2,
+}
diff --git a/wifi/aidl/android/hardware/wifi/Ssid.aidl b/wifi/aidl/android/hardware/wifi/Ssid.aidl
new file mode 100644
index 0000000..fd985a3
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/Ssid.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+/**
+ * Byte array representing an Ssid. Use when we need to
+ * pass an array of Ssid's to a method, as variable-sized
+ * 2D arrays are not supported in AIDL.
+ *
+ * TODO (b/210705533): Replace this type with a 2D byte array.
+ */
+@VintfStability
+parcelable Ssid {
+    byte[32] data;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaApfPacketFilterCapabilities.aidl b/wifi/aidl/android/hardware/wifi/StaApfPacketFilterCapabilities.aidl
new file mode 100644
index 0000000..5063b49
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaApfPacketFilterCapabilities.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.wifi;
+
+/**
+ * Parameters to specify the APF capabilities of this iface.
+ */
+@VintfStability
+parcelable StaApfPacketFilterCapabilities {
+    /**
+     * Version of the packet filter interpreter supported.
+     */
+    int version;
+    /**
+     * Maximum size of the filter bytecode in bytes for an iface.
+     */
+    int maxLength;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaBackgroundScanBucketEventReportSchemeMask.aidl b/wifi/aidl/android/hardware/wifi/StaBackgroundScanBucketEventReportSchemeMask.aidl
new file mode 100644
index 0000000..92e2928
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaBackgroundScanBucketEventReportSchemeMask.aidl
@@ -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 android.hardware.wifi;
+
+/**
+ * Mask of event reporting schemes that can be specified in background scan
+ * requests.
+ */
+@VintfStability
+@Backing(type="int")
+enum StaBackgroundScanBucketEventReportSchemeMask {
+    /**
+     * Report a scan completion event after scan. If this is not set, then scan
+     * completion events must be reported if report_threshold_percent or
+     * report_threshold_num_scans is reached.
+     */
+    EACH_SCAN = 1 << 0,
+    /**
+     * Forward scan results (beacons/probe responses + IEs) in real time to HAL,
+     * in addition to completion events.
+     * Note: To keep backward compatibility, fire completion events regardless
+     * of REPORT_EVENTS_EACH_SCAN.
+     */
+    FULL_RESULTS = 1 << 1,
+    /**
+     * Controls if scans for this bucket must be placed in the results buffer.
+     */
+    NO_BATCH = 1 << 2,
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaBackgroundScanBucketParameters.aidl b/wifi/aidl/android/hardware/wifi/StaBackgroundScanBucketParameters.aidl
new file mode 100644
index 0000000..7bd87b2
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaBackgroundScanBucketParameters.aidl
@@ -0,0 +1,71 @@
+/*
+ * 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;
+
+import android.hardware.wifi.StaBackgroundScanBucketEventReportSchemeMask;
+import android.hardware.wifi.WifiBand;
+
+/**
+ * Background Scan parameters per bucket that can be specified in background
+ * scan requests.
+ */
+@VintfStability
+parcelable StaBackgroundScanBucketParameters {
+    /**
+     * Bucket index. This index is used to report results in
+     * |StaScanData.bucketsScanned|.
+     */
+    int bucketIdx;
+    /**
+     * Bands to scan or |BAND_UNSPECIFIED| if frequencies list must be used
+     * instead.
+     */
+    WifiBand band;
+    /**
+     * Channel frequencies (in Mhz) to scan if |band| is set to
+     * |BAND_UNSPECIFIED|.
+     * Max length: |StaBackgroundScanLimits.MAX_CHANNELS|.
+     */
+    int[] frequencies;
+    /**
+     * Period at which this bucket must be scanned (in milliseconds). Must be an integer
+     * multiple of the |basePeriodInMs| specified in the BackgroundScanParameters.
+     */
+    int periodInMs;
+    /**
+     * Bitset of |StaBackgroundScanBucketEventReportSchemeMask| values controlling
+     * when events for this bucket must be reported.
+     */
+    StaBackgroundScanBucketEventReportSchemeMask eventReportScheme;
+    /**
+     * For exponential back off. If |exponentialMaxPeriodInMs| is non-zero or
+     * different than period, then this bucket is an exponential backoff bucket
+     * and the scan period must grow exponentially as per formula:
+     *   actual_period(N) = period * (base ^ (N/step_count))
+     * to this maximum period (in milliseconds).
+     */
+    int exponentialMaxPeriodInMs;
+    /**
+     * For exponential back off. Multiplier: new_period=old_period * base
+     */
+    int exponentialBase;
+    /**
+     * For exponential back off. Number of scans to perform for a given
+     * period.
+     */
+    int exponentialStepCount;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaBackgroundScanCapabilities.aidl b/wifi/aidl/android/hardware/wifi/StaBackgroundScanCapabilities.aidl
new file mode 100644
index 0000000..8dd9141
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaBackgroundScanCapabilities.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.wifi;
+
+/**
+ * Parameters to specify the Background Scan capabilities of this iface.
+ */
+@VintfStability
+parcelable StaBackgroundScanCapabilities {
+    /**
+     * Maximum number of bytes available for cached scan results.
+     */
+    int maxCacheSize;
+    /**
+     * Maximum number of buckets that can be supplied for a scan.
+     */
+    int maxBuckets;
+    /**
+     * Maximum number of APs that must be stored for each scan.
+     */
+    int maxApCachePerScan;
+    /**
+     * Max reporting number of scans threshold that can be specified in the scan
+     * parameters.
+     */
+    int maxReportingThreshold;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaBackgroundScanLimits.aidl b/wifi/aidl/android/hardware/wifi/StaBackgroundScanLimits.aidl
new file mode 100644
index 0000000..b6fc44c
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaBackgroundScanLimits.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+/**
+ * Max limits for background scan.
+ */
+@VintfStability
+@Backing(type="int")
+enum StaBackgroundScanLimits {
+    MAX_CHANNELS = 16,
+    MAX_BUCKETS = 16,
+    MAX_AP_CACHE_PER_SCAN = 32,
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaBackgroundScanParameters.aidl b/wifi/aidl/android/hardware/wifi/StaBackgroundScanParameters.aidl
new file mode 100644
index 0000000..0b56069
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaBackgroundScanParameters.aidl
@@ -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 android.hardware.wifi;
+
+import android.hardware.wifi.StaBackgroundScanBucketParameters;
+
+/**
+ * Background Scan parameters that can be specified in background scan
+ * requests.
+ */
+@VintfStability
+parcelable StaBackgroundScanParameters {
+    /**
+     * GCD of all bucket periods (in milliseconds).
+     */
+    int basePeriodInMs;
+    /**
+     * Maximum number of APs that must be stored for each scan. If the maximum
+     * is reached, then the highest RSSI results must be returned.
+     * Max length: |StaBackgroundScanLimits.MAX_AP_CACHE_PER_SCAN|.
+     */
+    int maxApPerScan;
+    /**
+     * % cache buffer filled threshold at which the host must be notified of
+     * batched scan results.
+     */
+    int reportThresholdPercent;
+    /**
+     * Threshold at which the AP must be woken up, in number of scans.
+     */
+    int reportThresholdNumScans;
+    /**
+     * List of buckets to be scheduled.
+     * Max length: |StaBackgroundScanLimits.MAX_BUCKETS|.
+     */
+    StaBackgroundScanBucketParameters[] buckets;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceContentionTimeStats.aidl b/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceContentionTimeStats.aidl
new file mode 100644
index 0000000..51f6916
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceContentionTimeStats.aidl
@@ -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 android.hardware.wifi;
+
+/**
+ * Contention time statistics for different traffic categories.
+ */
+@VintfStability
+parcelable StaLinkLayerIfaceContentionTimeStats {
+    /**
+     * Data packet min contention time (usec). This includes both the internal contention time
+     * among different access categories within the chipset and the contention time for the medium.
+     */
+    int contentionTimeMinInUsec;
+    /**
+     * Data packet max contention time (usec). This includes both the internal contention time
+     * among different access categories within the chipset and the contention time for the medium.
+     */
+    int contentionTimeMaxInUsec;
+    /**
+     * Data packet average contention time (usec). This includes both the internal contention time
+     * among different access categories within the chipset and the contention time for the medium.
+     */
+    int contentionTimeAvgInUsec;
+    /**
+     * Number of data packets used for contention statistics.
+     */
+    int contentionNumSamples;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaLinkLayerIfacePacketStats.aidl b/wifi/aidl/android/hardware/wifi/StaLinkLayerIfacePacketStats.aidl
new file mode 100644
index 0000000..c0e2c7b
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaLinkLayerIfacePacketStats.aidl
@@ -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 android.hardware.wifi;
+
+/**
+ * Packet stats for different traffic categories.
+ */
+@VintfStability
+parcelable StaLinkLayerIfacePacketStats {
+    /**
+     * Number of received unicast data packets.
+     */
+    long rxMpdu;
+    /**
+     * Number of successfully transmitted unicast data pkts (ACK rcvd).
+     */
+    long txMpdu;
+    /**
+     * Number of transmitted unicast data pkt losses (no ACK).
+     */
+    long lostMpdu;
+    /**
+     * Number of transmitted unicast data retry pkts.
+     */
+    long retries;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceStats.aidl b/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceStats.aidl
new file mode 100644
index 0000000..78f8caa
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceStats.aidl
@@ -0,0 +1,79 @@
+/*
+ * 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;
+
+import android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats;
+import android.hardware.wifi.StaLinkLayerIfacePacketStats;
+import android.hardware.wifi.StaPeerInfo;
+
+/**
+ * Iface statistics for the current connection.
+ */
+@VintfStability
+parcelable StaLinkLayerIfaceStats {
+    /**
+     * Number beacons received from the connected AP.
+     */
+    int beaconRx;
+    /**
+     * Access Point Beacon and Management frames RSSI (averaged).
+     */
+    int avgRssiMgmt;
+    /**
+     * WME Best Effort Access Category packet counters.
+     */
+    StaLinkLayerIfacePacketStats wmeBePktStats;
+    /**
+     * WME Background Access Category packet counters.
+     */
+    StaLinkLayerIfacePacketStats wmeBkPktStats;
+    /**
+     * WME Video Access Category packet counters.
+     */
+    StaLinkLayerIfacePacketStats wmeViPktStats;
+    /**
+     * WME Voice Access Category packet counters.
+     */
+    StaLinkLayerIfacePacketStats wmeVoPktStats;
+    /**
+     * Duty cycle for the iface.
+     * If this iface is being served using time slicing on a radio with one or more ifaces
+     * (i.e MCC), then the duty cycle assigned to this iface in %.
+     * If not using time slicing (i.e SCC or DBS), set to 100.
+     */
+    byte timeSliceDutyCycleInPercent;
+    /**
+     * WME Best Effort (BE) Access Category (AC) contention time statistics.
+     */
+    StaLinkLayerIfaceContentionTimeStats wmeBeContentionTimeStats;
+    /**
+     * WME Background (BK) Access Category (AC) contention time statistics.
+     */
+    StaLinkLayerIfaceContentionTimeStats wmeBkContentionTimeStats;
+    /**
+     * WME Video (VI) Access Category (AC) contention time statistics.
+     */
+    StaLinkLayerIfaceContentionTimeStats wmeViContentionTimeStats;
+    /**
+     * WME Voice (VO) Access Category (AC) contention time statistics.
+     */
+    StaLinkLayerIfaceContentionTimeStats wmeVoContentionTimeStats;
+    /**
+     * Per peer statistics.
+     */
+    StaPeerInfo[] peers;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaLinkLayerRadioStats.aidl b/wifi/aidl/android/hardware/wifi/StaLinkLayerRadioStats.aidl
new file mode 100644
index 0000000..6105172
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaLinkLayerRadioStats.aidl
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiChannelStats;
+
+@VintfStability
+parcelable StaLinkLayerRadioStats {
+    /**
+     * Time for which the radio is awake.
+     */
+    int onTimeInMs;
+    /**
+     * Total time for which the radio is in active transmission.
+     */
+    int txTimeInMs;
+    /**
+     * Time for which the radio is in active tranmission per tx level.
+     */
+    int[] txTimeInMsPerLevel;
+    /**
+     * Time for which the radio is in active receive.
+     */
+    int rxTimeInMs;
+    /**
+     *  Total time for which the radio is awake due to scan.
+     */
+    int onTimeInMsForScan;
+    /**
+     * Total time for which the radio is awake due to NAN scan since boot or crash.
+     */
+    int onTimeInMsForNanScan;
+    /**
+     * Total time for which the radio is awake due to background scan since boot or crash.
+     */
+    int onTimeInMsForBgScan;
+    /**
+     * Total time for which the radio is awake due to roam scan since boot or crash.
+     */
+    int onTimeInMsForRoamScan;
+    /**
+     * Total time for which the radio is awake due to PNO scan since boot or crash.
+     */
+    int onTimeInMsForPnoScan;
+    /**
+     * Total time for which the radio is awake due to Hotspot 2.0 scans and GAS exchange since boot
+     * or crash.
+     */
+    int onTimeInMsForHs20Scan;
+    /**
+     * List of channel stats associated with this radio.
+     */
+    WifiChannelStats[] channelStats;
+    /**
+     * Radio ID: An implementation specific value identifying the radio interface for which the
+     * stats are produced. Framework must not interpret this value. It must use this value for
+     * persistently identifying the statistics between calls,
+     * e.g. if the HAL provides them in different order.
+     */
+    int radioId;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaLinkLayerStats.aidl b/wifi/aidl/android/hardware/wifi/StaLinkLayerStats.aidl
new file mode 100644
index 0000000..32be121
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaLinkLayerStats.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+import android.hardware.wifi.StaLinkLayerIfaceStats;
+import android.hardware.wifi.StaLinkLayerRadioStats;
+
+/**
+ * Link layer stats retrieved via |IWifiStaIface.getLinkLayerStats|.
+ */
+@VintfStability
+parcelable StaLinkLayerStats {
+    StaLinkLayerIfaceStats iface;
+    StaLinkLayerRadioStats[] radios;
+    /**
+     * Timestamp for each stats sample. This is the absolute milliseconds
+     * from boot when these stats were sampled.
+     */
+    long timeStampInMs;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaPeerInfo.aidl b/wifi/aidl/android/hardware/wifi/StaPeerInfo.aidl
new file mode 100644
index 0000000..2032802
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaPeerInfo.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.wifi;
+
+import android.hardware.wifi.StaRateStat;
+
+/**
+ * Per peer statistics. Types of peers include the Access Point (AP), Tunneled Direct Link
+ * Setup (TDLS), Group Owner (GO), Neighbor Awareness Networking (NAN), etc.
+ */
+@VintfStability
+parcelable StaPeerInfo {
+    /**
+     * Station count: The total number of stations currently associated with the peer.
+     */
+    char staCount;
+    /**
+     * Channel utilization: The percentage of time (normalized to 255, i.e., x% corresponds to
+     * (int) x * 255 / 100) that the medium is sensed as busy measured by either physical or
+     * virtual carrier sense (CS) mechanism.
+     */
+    char chanUtil;
+    /**
+     * Per rate statistics.
+     */
+    StaRateStat[] rateStats;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaRateStat.aidl b/wifi/aidl/android/hardware/wifi/StaRateStat.aidl
new file mode 100644
index 0000000..8326884
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaRateStat.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiRateInfo;
+
+/**
+ * Per rate statistics. The rate is characterized by the combination of preamble, number
+ * of spatial streams, transmission bandwidth, and modulation and coding scheme (MCS).
+ */
+@VintfStability
+parcelable StaRateStat {
+    /**
+     * Wifi rate information: preamble, number of spatial streams, bandwidth, MCS, etc.
+     */
+    WifiRateInfo rateInfo;
+    /**
+     * Number of successfully transmitted data packets (ACK received).
+     */
+    int txMpdu;
+    /**
+     * Number of received data packets.
+     */
+    int rxMpdu;
+    /**
+     * Number of data packet losses (no ACK).
+     */
+    int mpduLost;
+    /**
+     * Number of data packet retries.
+     */
+    int retries;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaRoamingCapabilities.aidl b/wifi/aidl/android/hardware/wifi/StaRoamingCapabilities.aidl
new file mode 100644
index 0000000..7642612
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaRoamingCapabilities.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.wifi;
+
+/**
+ * Structure describing the roaming control capabilities supported.
+ */
+@VintfStability
+parcelable StaRoamingCapabilities {
+    /**
+     * Maximum number of BSSIDs that may be blocklisted.
+     */
+    int maxBlocklistSize;
+    /**
+     * Maximum number of SSIDs that may be allowlisted.
+     */
+    int maxAllowlistSize;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaRoamingConfig.aidl b/wifi/aidl/android/hardware/wifi/StaRoamingConfig.aidl
new file mode 100644
index 0000000..c59c531
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaRoamingConfig.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+import android.hardware.wifi.MacAddress;
+import android.hardware.wifi.Ssid;
+
+/**
+ * Structure describing the roaming control configuration.
+ */
+@VintfStability
+parcelable StaRoamingConfig {
+    /**
+     * List of BSSIDs that are blocklisted for roaming.
+     */
+    MacAddress[] bssidBlocklist;
+    /**
+     * List of SSIDs that are allowlisted for roaming.
+     */
+    Ssid[] ssidAllowlist;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaRoamingState.aidl b/wifi/aidl/android/hardware/wifi/StaRoamingState.aidl
new file mode 100644
index 0000000..d75d323
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaRoamingState.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+/**
+ * Enum describing the various states to set the roaming
+ * control to.
+ */
+@VintfStability
+@Backing(type="byte")
+enum StaRoamingState {
+    /**
+     * Driver/Firmware must not perform any roaming.
+     */
+    DISABLED = 0,
+    /**
+     * Driver/Firmware is allowed to perform roaming while respecting
+     * the |StaRoamingConfig| parameters set using |configureRoaming|.
+     */
+    ENABLED = 1,
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaScanData.aidl b/wifi/aidl/android/hardware/wifi/StaScanData.aidl
new file mode 100644
index 0000000..9d6bd53
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaScanData.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.wifi;
+
+import android.hardware.wifi.StaScanDataFlagMask;
+import android.hardware.wifi.StaScanResult;
+
+/**
+ * Structure describing all of the access points seen during
+ * the scan.
+ */
+@VintfStability
+parcelable StaScanData {
+    /**
+     * Bitset containing |ScanDataFlagMask| values.
+     */
+    StaScanDataFlagMask flags;
+    /**
+     * Bitset where each bit indicates if the bucket with that index (starting at
+     * 0) was scanned.
+     */
+    int bucketsScanned;
+    /**
+     * List of scan results.
+     */
+    StaScanResult[] results;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaScanDataFlagMask.aidl b/wifi/aidl/android/hardware/wifi/StaScanDataFlagMask.aidl
new file mode 100644
index 0000000..ea87df5
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaScanDataFlagMask.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ * Mask of flags set in the |ScanData| instance.
+ */
+@VintfStability
+@Backing(type="int")
+enum StaScanDataFlagMask {
+    /**
+     * Indicates that a scan was interrupted/did not occur, so results may be
+     * incomplete.
+     */
+    INTERRUPTED = 1 << 0,
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaScanResult.aidl b/wifi/aidl/android/hardware/wifi/StaScanResult.aidl
new file mode 100644
index 0000000..9f6f415
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaScanResult.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiInformationElement;
+
+/**
+ * Structure describing all the information about a single access point seen
+ * during the scan.
+ */
+@VintfStability
+parcelable StaScanResult {
+    long timeStampInUs;
+    byte[] ssid;
+    byte[6] bssid;
+    int rssi;
+    int frequency;
+    char beaconPeriodInMs;
+    char capability;
+    WifiInformationElement[] informationElements;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiAntennaMode.aidl b/wifi/aidl/android/hardware/wifi/WifiAntennaMode.aidl
new file mode 100644
index 0000000..e21dd87
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiAntennaMode.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ * Antenna configuration.
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiAntennaMode {
+    WIFI_ANTENNA_MODE_UNSPECIFIED = 0,
+    WIFI_ANTENNA_MODE_1X1 = 1,
+    WIFI_ANTENNA_MODE_2X2 = 2,
+    WIFI_ANTENNA_MODE_3X3 = 3,
+    WIFI_ANTENNA_MODE_4X4 = 4,
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiBand.aidl b/wifi/aidl/android/hardware/wifi/WifiBand.aidl
new file mode 100644
index 0000000..cfdf944
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiBand.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.wifi;
+
+/**
+ * Wifi bands defined in the 80211 spec.
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiBand {
+    BAND_UNSPECIFIED = 0,
+    /**
+     * 2.4 GHz.
+     */
+    BAND_24GHZ = 1,
+    /**
+     * 5 GHz without DFS.
+     */
+    BAND_5GHZ = 2,
+    /**
+     * 5 GHz DFS only.
+     */
+    BAND_5GHZ_DFS = 4,
+    /**
+     * 5 GHz with DFS.
+     */
+    BAND_5GHZ_WITH_DFS = 6,
+    /**
+     * 2.4 GHz + 5 GHz; no DFS.
+     */
+    BAND_24GHZ_5GHZ = 3,
+    /**
+     * 2.4 GHz + 5 GHz with DFS.
+     */
+    BAND_24GHZ_5GHZ_WITH_DFS = 7,
+    /**
+     * 6 GHz.
+     */
+    BAND_6GHZ = 8,
+    /**
+     * 5 GHz no DFS + 6 GHz.
+     */
+    BAND_5GHZ_6GHZ = 10,
+    /**
+     * 2.4 GHz + 5 GHz no DFS + 6 GHz.
+     */
+    BAND_24GHZ_5GHZ_6GHZ = 11,
+    /**
+     * 2.4 GHz + 5 GHz with DFS + 6 GHz.
+     */
+    BAND_24GHZ_5GHZ_WITH_DFS_6GHZ = 15,
+    /**
+     * 60 GHz.
+     */
+    BAND_60GHZ = 16,
+    /**
+     * 2.4 GHz + 5 GHz no DFS + 6 GHz + 60 GHz.
+     */
+    BAND_24GHZ_5GHZ_6GHZ_60GHZ = 27,
+    /**
+     * 2.4 GHz + 5 GHz with DFS + 6 GHz + 60 GHz.
+     */
+    BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ = 31,
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiChannelInfo.aidl b/wifi/aidl/android/hardware/wifi/WifiChannelInfo.aidl
new file mode 100644
index 0000000..8fee7eb
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiChannelInfo.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiChannelWidthInMhz;
+
+/**
+ * Channel information.
+ */
+@VintfStability
+parcelable WifiChannelInfo {
+    /**
+     * Channel width (20, 40, 80, 80+80, 160, 320).
+     */
+    WifiChannelWidthInMhz width;
+    /**
+     * Primary 20 MHz channel.
+     */
+    int centerFreq;
+    /**
+     * Center frequency (MHz) first segment.
+     */
+    int centerFreq0;
+    /**
+     * Center frequency (MHz) second segment.
+     */
+    int centerFreq1;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiChannelStats.aidl b/wifi/aidl/android/hardware/wifi/WifiChannelStats.aidl
new file mode 100644
index 0000000..f77821b
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiChannelStats.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiChannelInfo;
+
+@VintfStability
+parcelable WifiChannelStats {
+    /**
+     * Channel information.
+     */
+    WifiChannelInfo channel;
+    /**
+     * Total time for which the radio is awake on this channel.
+     */
+    int onTimeInMs;
+    /**
+     * Total time for which CCA is held busy on this channel.
+     */
+    int ccaBusyTimeInMs;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiChannelWidthInMhz.aidl b/wifi/aidl/android/hardware/wifi/WifiChannelWidthInMhz.aidl
new file mode 100644
index 0000000..e456530
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiChannelWidthInMhz.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;
+
+/**
+ * Channel operating width in Mhz.
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiChannelWidthInMhz {
+    WIDTH_INVALID = -1,
+    WIDTH_20 = 0,
+    WIDTH_40 = 1,
+    WIDTH_80 = 2,
+    WIDTH_160 = 3,
+    WIDTH_80P80 = 4,
+    WIDTH_5 = 5,
+    WIDTH_10 = 6,
+    /**
+     * 320 MHz
+     */
+    WIDTH_320 = 7,
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugHostWakeReasonRxIcmpPacketDetails.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugHostWakeReasonRxIcmpPacketDetails.aidl
new file mode 100644
index 0000000..8cf4819
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugHostWakeReasonRxIcmpPacketDetails.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+/**
+ * Struct capturing the count of all rx ICMP packets that caused
+ * host wakeup.
+ */
+@VintfStability
+parcelable WifiDebugHostWakeReasonRxIcmpPacketDetails {
+    /**
+     * Wake icmp packet count.
+     */
+    int icmpPkt;
+    /**
+     * Wake icmp6 packet count.
+     */
+    int icmp6Pkt;
+    /**
+     * Wake icmp6 RA packet count.
+     */
+    int icmp6Ra;
+    /**
+     * Wake icmp6 NA packet count.
+     */
+    int icmp6Na;
+    /**
+     * Wake icmp6 NS packet count.
+     */
+    int icmp6Ns;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugHostWakeReasonRxMulticastPacketDetails.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugHostWakeReasonRxMulticastPacketDetails.aidl
new file mode 100644
index 0000000..51faf66
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugHostWakeReasonRxMulticastPacketDetails.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;
+
+/**
+ * Struct capturing the count of all rx multicast packets that caused
+ * host wakeup.
+ */
+@VintfStability
+parcelable WifiDebugHostWakeReasonRxMulticastPacketDetails {
+    /**
+     * Rx wake packet was ipv4 multicast.
+     */
+    int ipv4RxMulticastAddrCnt;
+    /**
+     * Rx wake packet was ipv6 multicast.
+     */
+    int ipv6RxMulticastAddrCnt;
+    /**
+     * Rx wake packet was non-ipv4 and non-ipv6.
+     */
+    int otherRxMulticastAddrCnt;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugHostWakeReasonRxPacketDetails.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugHostWakeReasonRxPacketDetails.aidl
new file mode 100644
index 0000000..b5c6a5e
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugHostWakeReasonRxPacketDetails.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;
+
+/**
+ * Struct capturing the count of all rx packets that caused
+ * host wakeup.
+ */
+@VintfStability
+parcelable WifiDebugHostWakeReasonRxPacketDetails {
+    /**
+     * Total rx unicast packet which woke up host.
+     */
+    int rxUnicastCnt;
+    /**
+     * Total rx multicast packet which woke up host.
+     */
+    int rxMulticastCnt;
+    /**
+     * Total rx broadcast packet which woke up host.
+     */
+    int rxBroadcastCnt;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugHostWakeReasonStats.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugHostWakeReasonStats.aidl
new file mode 100644
index 0000000..82d5d3e
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugHostWakeReasonStats.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.wifi;
+
+import android.hardware.wifi.WifiDebugHostWakeReasonRxIcmpPacketDetails;
+import android.hardware.wifi.WifiDebugHostWakeReasonRxMulticastPacketDetails;
+import android.hardware.wifi.WifiDebugHostWakeReasonRxPacketDetails;
+
+/**
+ * Structure capturing the count of all the wireless related host wakeup.
+ * This is used to capture all the reasons why the host processor
+ * (WLAN driver) was woken up by the WLAN firmware.
+ * These stats may be used to debug any power issues caused due to frequent
+ * wakeup of the host processor by the WLAN firmware.
+ */
+@VintfStability
+parcelable WifiDebugHostWakeReasonStats {
+    /**
+     * Total count of cmd/event wakes.
+     * These must account for all wakeups due to WLAN management
+     * commands/events received over the air.
+     */
+    int totalCmdEventWakeCnt;
+    /**
+     * Vector of wake counts per cmd/event type.
+     * The number of command types and their meaning is only understood by the
+     * vendor.
+     */
+    int[] cmdEventWakeCntPerType;
+    /**
+     * Total count of driver/firmware wakes.
+     * These must account for all wakeups due to local driver/firmware
+     * interactions. These include all vendor implementation specific
+     * interactions like any heart-beat monitoring, bus management, etc.
+     */
+    int totalDriverFwLocalWakeCnt;
+    /**
+     * Vector of wake counts per driver/firmware interaction type.
+     * The number of command types and their meaning is only understood by the
+     * vendor.
+     */
+    int[] driverFwLocalWakeCntPerType;
+    /**
+     * Total data rx packets that woke up host.
+     */
+    int totalRxPacketWakeCnt;
+    WifiDebugHostWakeReasonRxPacketDetails rxPktWakeDetails;
+    WifiDebugHostWakeReasonRxMulticastPacketDetails rxMulticastPkWakeDetails;
+    WifiDebugHostWakeReasonRxIcmpPacketDetails rxIcmpPkWakeDetails;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugPacketFateFrameInfo.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugPacketFateFrameInfo.aidl
new file mode 100644
index 0000000..7601bf2
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugPacketFateFrameInfo.aidl
@@ -0,0 +1,70 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiDebugPacketFateFrameType;
+
+/**
+ * Information regarding the frame transmitted/received.
+ */
+@VintfStability
+parcelable WifiDebugPacketFateFrameInfo {
+    /**
+     * The type of MAC-layer frame that this frame_info holds.
+     * - For data frames, use FRAME_TYPE_ETHERNET_II.
+     * - For management frames, use FRAME_TYPE_80211_MGMT.
+     * - If the type of the frame is unknown, use FRAME_TYPE_UNKNOWN.
+     */
+    WifiDebugPacketFateFrameType frameType;
+    /**
+     * The number of bytes included in |frameContent|.
+     * If the frame contents are missing (e.g. RX frame dropped in firmware),
+     * |frameLen| must be set to 0.
+     */
+    long frameLen;
+    /**
+     * Host clock when this frame was received by the driver (either outbound
+     * from the host network stack, or inbound from the firmware).
+     * - The timestamp must be taken from a clock which includes time the host
+     *   spent suspended (e.g. ktime_get_boottime()).
+     * - If no host timestamp is available (e.g. RX frame was dropped in firmware),
+     *   this field must be set to 0.
+     */
+    long driverTimestampUsec;
+    /**
+     * Firmware clock when this frame was received by the firmware
+     * (either outbound from the host, or inbound from a remote  station).
+     * - The timestamp must be taken from a clock which includes time firmware
+     *   spent suspended (if applicable).
+     * - If no firmware timestamp is available (e.g. TX frame was dropped by the
+     *   driver), then this field must be set to 0.
+     * - Consumers of |frameInfo| must not assume any synchronization between
+     *   the driver and firmware clocks.
+     */
+    long firmwareTimestampUsec;
+    /**
+     * Actual frame content. This is the raw bytes of the corresponding packet.
+     * - Should be provided for TX frames originated by the host.
+     * - Should be provided for RX frames received by the driver.
+     * - Optionally provided for TX frames originated by firmware.
+     *   (At discretion of HAL implementation.)
+     * - Optionally provided for RX frames dropped in firmware.
+     *   (At discretion of HAL implementation.)
+     * - If frame content is not provided, |frameLen| must be set to 0.
+     */
+    byte[] frameContent;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugPacketFateFrameType.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugPacketFateFrameType.aidl
new file mode 100644
index 0000000..5c0d171
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugPacketFateFrameType.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+/**
+ * Type of frame transmitted/received.
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiDebugPacketFateFrameType {
+    UNKNOWN,
+    ETHERNET_II,
+    MGMT_80211,
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugRingBufferFlags.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugRingBufferFlags.aidl
new file mode 100644
index 0000000..0d1806e
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugRingBufferFlags.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+/**
+ * Flags describing each debug ring buffer.
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiDebugRingBufferFlags {
+    HAS_BINARY_ENTRIES = 1 << 0,
+    HAS_ASCII_ENTRIES = 1 << 1,
+    HAS_PER_PACKET_ENTRIES = 1 << 2,
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugRingBufferStatus.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugRingBufferStatus.aidl
new file mode 100644
index 0000000..2b0faa2
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugRingBufferStatus.aidl
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+/**
+ * Struct describing each debug ring buffer supported by
+ * the device.
+ */
+@VintfStability
+parcelable WifiDebugRingBufferStatus {
+    /**
+     * Name of this debug ring buffer.
+     */
+    String ringName;
+    /**
+     * Combination of |WifiDebugRingBufferFlags| values.
+     */
+    int flags;
+    /**
+     * Unique integer representing the ring.
+     */
+    int ringId;
+    /**
+     * Total memory size allocated for the buffer.
+     */
+    int sizeInBytes;
+    /**
+     * Amount of free space in the buffer.
+     */
+    int freeSizeInBytes;
+    /**
+     * Verbose level for ring buffer.
+     */
+    int verboseLevel;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugRingBufferVerboseLevel.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugRingBufferVerboseLevel.aidl
new file mode 100644
index 0000000..30778eb
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugRingBufferVerboseLevel.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+/**
+ * Verbose logging level to set for each debug ring buffer supported
+ * by the device.
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiDebugRingBufferVerboseLevel {
+    /**
+     * Level 0 corresponds to no collection, and it makes log handler
+     * stop by no more events from driver.
+     */
+    NONE = 0,
+    /**
+     * Level 1 corresponds to normal log level, with minimal user impact.
+     * This is the default value.
+     */
+    DEFAULT = 1,
+    /**
+     * Level 2 is enabled when user is lazily trying to reproduce a problem.
+     * Wifi performance and power can be impacted, but device should not
+     * otherwise be significantly impacted.
+     */
+    VERBOSE = 2,
+    /**
+     * Level 3 is used when trying to actively debug a problem.
+     * This will cause severe performance degradation.
+     */
+    EXCESSIVE = 3,
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugRxPacketFate.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugRxPacketFate.aidl
new file mode 100644
index 0000000..2983f81
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugRxPacketFate.aidl
@@ -0,0 +1,70 @@
+/*
+ * 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;
+
+/**
+ * Enum describing the fate of the RX packets.
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiDebugRxPacketFate {
+    /**
+     * Valid and delivered to network stack (e.g., netif_rx()).
+     */
+    SUCCESS,
+    /**
+     * Queued within firmware, but not yet sent to driver.
+     */
+    FW_QUEUED,
+    /**
+     * Dropped by firmware due to host-programmable filters.
+     */
+    FW_DROP_FILTER,
+    /**
+     * Dropped by firmware as invalid (e.g. bad checksum, decrypt failed,
+     * or invalid for current state).
+     */
+    FW_DROP_INVALID,
+    /**
+     * Dropped by firmware due to lack of buffer space.
+     */
+    FW_DROP_NOBUFS,
+    /**
+     * Dropped by firmware for any other reason.
+     */
+    FW_DROP_OTHER,
+    /**
+     * Queued within driver, not yet delivered to network stack.
+     */
+    DRV_QUEUED,
+    /**
+     * Dropped by driver due to filter rules.
+     */
+    DRV_DROP_FILTER,
+    /**
+     * Dropped by driver as invalid (e.g. not permitted in current state).
+     */
+    DRV_DROP_INVALID,
+    /**
+     * Dropped by driver due to lack of buffer space.
+     */
+    DRV_DROP_NOBUFS,
+    /**
+     * Dropped by driver for any other reason.
+     */
+    DRV_DROP_OTHER,
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugRxPacketFateReport.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugRxPacketFateReport.aidl
new file mode 100644
index 0000000..f4d709c
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugRxPacketFateReport.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiDebugPacketFateFrameInfo;
+import android.hardware.wifi.WifiDebugRxPacketFate;
+
+/**
+ * Struct describing packet fate report for each Rx frame.
+ */
+@VintfStability
+parcelable WifiDebugRxPacketFateReport {
+    WifiDebugRxPacketFate fate;
+    WifiDebugPacketFateFrameInfo frameInfo;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugTxPacketFate.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugTxPacketFate.aidl
new file mode 100644
index 0000000..717d62a
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugTxPacketFate.aidl
@@ -0,0 +1,68 @@
+/*
+ * 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;
+
+/**
+ * Enum describing the fate of the TX packets.
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiDebugTxPacketFate {
+    /**
+     * Sent over air and ACKed.
+     */
+    ACKED,
+    /**
+     * Sent over air but not ACKed (normal for broadcast/multicast).
+     */
+    SENT,
+    /**
+     * Queued within firmware, but not yet sent over air.
+     */
+    FW_QUEUED,
+    /**
+     * Dropped by firmware as invalid (e.g. bad source address, bad checksum,
+     * or invalid for current state).
+     */
+    FW_DROP_INVALID,
+    /**
+     * Dropped by firmware due to lack of buffer space.
+     */
+    FW_DROP_NOBUFS,
+    /**
+     * Dropped by firmware for any other reason. Includes frames that were sent
+     * by driver to the firmware, but unaccounted for by firmware.
+     */
+    FW_DROP_OTHER,
+    /**
+     * Queued within driver, not yet sent to firmware.
+     */
+    DRV_QUEUED,
+    /**
+     * Dropped by driver as invalid (e.g. bad source address, or invalid for
+     * current state).
+     */
+    DRV_DROP_INVALID,
+    /**
+     * Dropped by driver due to lack of buffer space.
+     */
+    DRV_DROP_NOBUFS,
+    /**
+     * Dropped by driver for any other reason.
+     */
+    DRV_DROP_OTHER,
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiDebugTxPacketFateReport.aidl b/wifi/aidl/android/hardware/wifi/WifiDebugTxPacketFateReport.aidl
new file mode 100644
index 0000000..b59b0a5
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiDebugTxPacketFateReport.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiDebugPacketFateFrameInfo;
+import android.hardware.wifi.WifiDebugTxPacketFate;
+
+/**
+ * Struct describing packet fate report for each Tx frame.
+ */
+@VintfStability
+parcelable WifiDebugTxPacketFateReport {
+    WifiDebugTxPacketFate fate;
+    WifiDebugPacketFateFrameInfo frameInfo;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiIfaceMode.aidl b/wifi/aidl/android/hardware/wifi/WifiIfaceMode.aidl
new file mode 100644
index 0000000..f70c744
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiIfaceMode.aidl
@@ -0,0 +1,57 @@
+/*
+ * 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;
+
+/**
+ * Interface operating modes.
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiIfaceMode {
+    /**
+     * Interface operation mode is client.
+     */
+    IFACE_MODE_STA = 1 << 0,
+    /**
+     * Interface operation mode is Hotspot.
+     */
+    IFACE_MODE_SOFTAP = 1 << 1,
+    /**
+     * Interface operation mode is Ad-Hoc network.
+     */
+    IFACE_MODE_IBSS = 1 << 2,
+    /**
+     * Interface operation mode is Wifi Direct Client.
+     */
+    IFACE_MODE_P2P_CLIENT = 1 << 3,
+    /**
+     * Interface operation mode is Wifi Direct Group Owner.
+     */
+    IFACE_MODE_P2P_GO = 1 << 4,
+    /**
+     * Interface operation mode is Aware.
+     */
+    IFACE_MODE_NAN = 1 << 5,
+    /**
+     * Interface operation mode is Mesh network.
+     */
+    IFACE_MODE_MESH = 1 << 6,
+    /**
+     * Interface operation mode is Tunneled Direct Link Setup.
+     */
+    IFACE_MODE_TDLS = 1 << 7,
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiInformationElement.aidl b/wifi/aidl/android/hardware/wifi/WifiInformationElement.aidl
new file mode 100644
index 0000000..f5f6de9
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiInformationElement.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+/**
+ * Information elements contained within the |ScanResult| structure.
+ * These elements correspond to the IEEE_802.11 standard.
+ */
+@VintfStability
+parcelable WifiInformationElement {
+    byte id;
+    byte[] data;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiRadioCombination.aidl b/wifi/aidl/android/hardware/wifi/WifiRadioCombination.aidl
new file mode 100644
index 0000000..28b15ed
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiRadioCombination.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiRadioConfiguration;
+
+/**
+ * Wifi radio combination.
+ */
+@VintfStability
+parcelable WifiRadioCombination {
+    /**
+     * List of radio configurations in this combination.
+     */
+    WifiRadioConfiguration[] radioConfigurations;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiRadioCombinationMatrix.aidl b/wifi/aidl/android/hardware/wifi/WifiRadioCombinationMatrix.aidl
new file mode 100644
index 0000000..b79a818
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiRadioCombinationMatrix.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiRadioCombination;
+
+/**
+ * Wifi radio combinations matrix retrieved via
+ * |IWifiChip.getSupportedRadioCombinationsMatrix|.
+ */
+@VintfStability
+parcelable WifiRadioCombinationMatrix {
+    /**
+     * List of all the possible radio combinations that the chip can operate.
+     */
+    WifiRadioCombination[] radioCombinations;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiRadioConfiguration.aidl b/wifi/aidl/android/hardware/wifi/WifiRadioConfiguration.aidl
new file mode 100644
index 0000000..ae8eff3
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiRadioConfiguration.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiAntennaMode;
+import android.hardware.wifi.WifiBand;
+
+/**
+ * Wifi radio configuration.
+ */
+@VintfStability
+parcelable WifiRadioConfiguration {
+    /**
+     * Band on which this radio chain is operating.
+     * Valid values of bandInfo are: BAND_24GHZ, BAND_5GHZ, BAND_6GHZ and
+     * BAND_60GHZ.
+     *
+     */
+    WifiBand bandInfo;
+    /**
+     * Wifi Antenna configuration.
+     */
+    WifiAntennaMode antennaMode;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiRateInfo.aidl b/wifi/aidl/android/hardware/wifi/WifiRateInfo.aidl
new file mode 100644
index 0000000..c4e285e
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiRateInfo.aidl
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiChannelWidthInMhz;
+import android.hardware.wifi.WifiRateNss;
+import android.hardware.wifi.WifiRatePreamble;
+
+/**
+ * Wifi rate info.
+ */
+@VintfStability
+parcelable WifiRateInfo {
+    /**
+     * Preamble used for RTT measurements.
+     */
+    WifiRatePreamble preamble;
+    /**
+     * Number of spatial streams.
+     */
+    WifiRateNss nss;
+    /**
+     * Bandwidth of channel.
+     */
+    WifiChannelWidthInMhz bw;
+    /**
+     * OFDM/CCK rate code as per IEEE std in units of 0.5mbps.
+     * HT/VHT/HE/EHT would be mcs index.
+     */
+    byte rateMcsIdx;
+    /**
+     * Bitrate in units of 100 Kbps.
+     */
+    int bitRateInKbps;
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiRateNss.aidl b/wifi/aidl/android/hardware/wifi/WifiRateNss.aidl
new file mode 100644
index 0000000..0c263a5
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiRateNss.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+/**
+ * Number of spatial streams in VHT/HT.
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiRateNss {
+    NSS_1x1 = 0,
+    NSS_2x2 = 1,
+    NSS_3x3 = 2,
+    NSS_4x4 = 3,
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiRatePreamble.aidl b/wifi/aidl/android/hardware/wifi/WifiRatePreamble.aidl
new file mode 100644
index 0000000..116e46a
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiRatePreamble.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Wifi Rate Preamble.
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiRatePreamble {
+    OFDM = 0,
+    CCK = 1,
+    HT = 2,
+    VHT = 3,
+    RESERVED = 4,
+    /**
+     * Preamble type for 11ax.
+     */
+    HE = 5,
+    /**
+     * Preamble type for 11be.
+     */
+    EHT = 6,
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiStatusCode.aidl b/wifi/aidl/android/hardware/wifi/WifiStatusCode.aidl
new file mode 100644
index 0000000..30817f3
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiStatusCode.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+/**
+ * Enum values indicating the status of the WiFi operation.
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiStatusCode {
+    /**
+     * No errors.
+     */
+    SUCCESS,
+    /**
+     * Method invoked on an invalid |IWifiChip| object.
+     */
+    ERROR_WIFI_CHIP_INVALID,
+    /**
+     * Method invoked on an invalid |IWifiIface| object.
+     */
+    ERROR_WIFI_IFACE_INVALID,
+    /**
+     * Method invoked on an invalid |IWifiRttController| object.
+     */
+    ERROR_WIFI_RTT_CONTROLLER_INVALID,
+    ERROR_NOT_SUPPORTED,
+    ERROR_NOT_AVAILABLE,
+    ERROR_NOT_STARTED,
+    ERROR_INVALID_ARGS,
+    ERROR_BUSY,
+    ERROR_UNKNOWN,
+}
diff --git a/wifi/aidl/android/hardware/wifi/WifiUsableChannel.aidl b/wifi/aidl/android/hardware/wifi/WifiUsableChannel.aidl
new file mode 100644
index 0000000..d92e4cc
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/WifiUsableChannel.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+import android.hardware.wifi.WifiChannelWidthInMhz;
+import android.hardware.wifi.WifiIfaceMode;
+
+/**
+ * Wifi usable channel information.
+ */
+@VintfStability
+parcelable WifiUsableChannel {
+    /**
+     * Wifi channel freqeuncy in MHz.
+     */
+    int channel;
+    /**
+     * Wifi channel bandwidth in MHz.
+     */
+    WifiChannelWidthInMhz channelBandwidth;
+    /**
+     * Iface modes feasible on this channel.
+     */
+    WifiIfaceMode ifaceModeMask;
+}
diff --git a/wifi/apex/Android.bp b/wifi/apex/Android.bp
new file mode 100644
index 0000000..0afb96b
--- /dev/null
+++ b/wifi/apex/Android.bp
@@ -0,0 +1,55 @@
+package {
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+apex_key {
+    name: "com.android.hardware.wifi.key",
+    public_key: "com.android.hardware.wifi.avbpubkey",
+    private_key: "com.android.hardware.wifi.pem",
+}
+
+android_app_certificate {
+    name: "com.android.hardware.wifi.certificate",
+    certificate: "com.android.hardware.wifi",
+}
+
+genrule {
+    name: "gen-android.hardware.wifi.rc",
+    srcs: [":default-android.hardware.wifi@1.0-service.rc"],
+    out: ["com.android.hardware.wifi-service.rc"],
+    cmd: "sed -e 's@/vendor/bin/@/apex/com.android.hardware.wifi/bin/@' $(in) > $(out)",
+}
+
+prebuilt_etc {
+    name: "com.android.hardware.wifi.rc",
+    src: ":gen-android.hardware.wifi.rc",
+    installable: false,
+}
+
+prebuilt_etc {
+    name: "com.android.hardware.wifi.xml",
+    src: ":default-android.hardware.wifi@1.0-service.xml",
+    installable: false,
+}
+
+apex {
+    name: "com.android.hardware.wifi",
+    manifest: "apex_manifest.json",
+    key: "com.android.hardware.wifi.key",
+    certificate: ":com.android.hardware.wifi.certificate",
+    file_contexts: "file_contexts",
+    vintf_fragments: [":com.android.hardware.wifi.xml"],
+    use_vndk_as_stable: true,
+    updatable: false,
+    soc_specific: true,
+    binaries: [
+        "android.hardware.wifi@1.0-service",
+    ],
+    prebuilts: [
+        "com.android.hardware.wifi.rc",
+        "com.android.hardware.wifi.xml",
+    ],
+    overrides: [
+        "android.hardware.wifi@1.0-service",
+    ],
+}
diff --git a/wifi/apex/apex_manifest.json b/wifi/apex/apex_manifest.json
new file mode 100644
index 0000000..cab0814
--- /dev/null
+++ b/wifi/apex/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+    "name": "com.android.hardware.wifi",
+    "version": 1
+}
diff --git a/wifi/apex/com.android.hardware.wifi.avbpubkey b/wifi/apex/com.android.hardware.wifi.avbpubkey
new file mode 100644
index 0000000..63fba77
--- /dev/null
+++ b/wifi/apex/com.android.hardware.wifi.avbpubkey
Binary files differ
diff --git a/wifi/apex/com.android.hardware.wifi.pem b/wifi/apex/com.android.hardware.wifi.pem
new file mode 100644
index 0000000..9e589ac
--- /dev/null
+++ b/wifi/apex/com.android.hardware.wifi.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQCtT/vNnVVg2QVD
+eMdG+YZ8qYz/fbAQF9hnH8dE5RWHXzoYItBG7DSOuVT4T6POBVmFaVKlWDd7tDyw
+nFO3MmE2/FzhVSiBPwhMITa7UIERr3od3rWJ5g6oaTCOu4wa98L466Jp60f2fYSZ
+M9lGiKaDpLDSpxTU9hexjp7C4PfinnkYnlHBnrFXTmiO6f8AvOEwFFx73/rUNoe7
+F3TkGvjZDqHvE+pjz/nilkhXYuOl3zgSaeznJ9+TO5C/Z+Xr+zRhaJGI4v5Dkgmc
+jNy74+0hjwobXO3iWE44InQMvMh8zDKBx9l1oSsFoG3waj9ayqSYD7M74RX3PkUL
+QrhgAHZWi5iEnpu50xBzAqZB1ZDVkdZiKiGzweJ8OqltnVpvzlnW3rA3y3HtFyLm
+73C4ll9MdLaw266vBxgZfFOcjpphbbh9J9uGjOCJY1AxUzsqKygFD2CyOdb1jab3
+AC6VvRa+bLtv8fd2etp3atXv+Y9ACUX6zNK6Oa8Zktoo2Z//OLtcrk7xhgKKDkUF
+OPQrIjW9x0fdClDioIS+y7EHNUrfyRL7XPtUqGCszgz5jK2SMVGMpFaEtfbyNP1H
+BTGXdzcDP0RZdOOKTdBFgoRW5+6TH5CU9Nl4uevpxzwsTkXg0a+W1BGP+s9J7ssH
+rNPmHz+pbKZPDs/nxlpsKq+N+K8cCwIDAQABAoICAAJL943Lgnikl53DyXxGzUH0
+q0Itg7pK3prLQIRItubS2727JGB0O+QST650u7p8tql+clJvn1ib1FwQzkk0uTYV
+1RNFYiKIV89Od1+3GubFmQwxSd2Yd2RC9JpHoP0wgFx1HvNhY1RAaJPxLHVzVSWU
+dqVsAmoqErlPJwp1GcPejsNFQdcbh8Uc7GTMdA0p86AD/Q/FMZlDWbwgfPOS6e5S
+c9HrxSTqeijHDhFeZZ7qnN8dmT6c+CkG1o26zkC41QJfdOJIA8+YbVkuQrSYuilC
+MIOZUSu5ONwklL4geFWzDQ5MPDUDXEMYU6ymc817tv+u4ZSvEG/02sxh53iaOPc6
+C6im4nm6ZlRP9HzIvLAiRSbvwEb9cnLKgYpioSGXehDYg3zMPURwoqIxw+7IlIUh
+s+rhmCJV62PK1Z0nmo7m7S8r+z6j4G7aztGcbvdecocOJYOQB1VB8Zh4bNEIWp0a
+GDteG6aWXOCHoYRWAOluppDWa7Z+EgesU3Oj9Prn/ekUzzXx3V30zSTZYxRnQCO0
+vZIZ6hrlsNJcNrDpxmiWBaEOd4k5QI39pu6fDHc+UEEJMN+7eVk8d9QVA/LhrCjc
+JH1EVjtWosMUeMaMTpcmHTQKnEvmT2LO2fxGlF4JvjzDdVMloJrIP2LSQjovo2PX
+x9UXVu8Dt3kQRefZ42XxAoIBAQDkBoSYVajaFlyv9lW8oPmrQyzp93ite+TKVR8z
+PmcFQukjp5Gm8PGlGtGoH8aeE9Ev+R86aNPFy4n4ZJ7fmZYH1hxZ6dSc/56k6lLn
+uVKvTudYqwcRgBKuSZ8IDPFz3sHd+MnOBonDIri28fcBTDNv4LJP/6cAUoIOCCPm
+lQtJBfMNMDOXG4jv1Rv/1P5opGFATerRCubOxmeaFhZIDEjvN5WvLK5jmL7I8lX3
+X+gPiMHFWBQFmVTOHeVYEORDO5xFCOvHqCVB78b2xe1NkkrQ0CexpdflJVLE9IWt
+wWH43nhjxaK+eiBPrj37BliJvNaYfuxqcAj3p8c5KweFEtP7AoIBAQDCkx72K/Ja
+rFrrI0Avfo+3n6yoTMtMkiVhMuIKKPBJ2o4Opc/uixk+uLH5UH0X5GZsE51FAhUD
+L3bWMxV+vzVefWS8Iryo94ucvnfqhsN3KZXHDGoAuYv72jND8qPLKksM0dceMBfl
+aoyXSPAe8zAZeEx4iR2axgtnA0EbiXIaNVE/LF+WYdM74jvk/QtRzJ8IAAkSc5Rr
+GiTHeeP3nRnkjWjkmwKXYSJHcrEl26c/2ckeZORtblqxR9wMU5OgvJvMSzmOIpVH
+Y5lylZUOTuJCkApHFNKdRsawsSNKsy4yfY1byN/WkODb7le6Crt1gcwldMxDZAo9
+iB25FHq4zksxAoIBAQC+SBYkDO9PtnN4PycCto5B9VeokmN42bdthKT5nSxY/qIQ
+p8fquIvdzEiCdKnIxh69WrVNh6aZGyWySz0suDyzo1+bRH6w2LrpQcUXK9YtBroV
+ivrmBqsQF82G6U4f9BZxhifZLimN1g6wU7Bcu9r8lFQYX+1bXn66+N4EkAGP2VAe
+hEe45Dhccsjfrzzx06J4B81YzjEXAgf4VFAZpW7DeO4G9VE9OXyTsW49dSHwvJ1+
+ceabWX2kVtxIpiflVvwru6sNvGoC4PV2fmptXhPitqE5JHzJ8mBkjOx0t7hq9jMe
+hxEsxDrsYynDrWL65cNqFBhzJbTF/ZNJSHgI+1I7AoIBAQC7m0shJOJ61vCbA9Qh
+dzBvZn/9jn3/CHMOMxeLoEl/jEGokevZHzlqJn9D2n2jCdBPqOHc5dMIzT0R7xNs
+sERvJQx58ixh5r0wlt3cva++N9R4pdmXdVApuAvyGgQgIllWtQVr0AdaZs/EFsmf
+re/Uvw9MsThgQVBBNPwT5wSjjIEYHlrUDuKzPMFvWyUM6/Tyq8YTimmykvSfeUF7
+QHj0y/w1X9ixyTBaH5X64L10bTLkIXe2o87CXH0pTXRsaS73XhjSmTnCKaCMwPmF
+YD383BFs1AD3MITnXQSgQ//pIvGnbBmXMv38UOU5NpvlAw+pleJVoCHXjmTKTZq+
+kfohAoIBAQCrEecN8XEPjGdtY71rDYEwHGM6G4czHX0PNhlMjQos3aBVZ/YvVxPG
+pkXbms3GRXv4W92u7b2MwEKBPxcBepEdDZN9wSpe63bDFE6gpkipDhgj97JlLEUd
+s7h6oOoazdxmsRZyFho99SRQWrvyOiiKdLJCRZiqjUB4roOQmy7f9VAz6+OxyGV9
+XZigwW6bfUzMCmhx5Ss6zW8wZI+gINQh+2sDmiBiMQv14Ya5zlNYN+4/257Sk/jS
+o3QUDJITbReq/DNZ6UUzQS+AZ7ztc81rk5kRg0I33FZarRJ7TLAz+XmZZFoIOORz
+etEvMk8bJ4u7X89NWW/i2J+kQiDQg819
+-----END PRIVATE KEY-----
diff --git a/wifi/apex/com.android.hardware.wifi.pk8 b/wifi/apex/com.android.hardware.wifi.pk8
new file mode 100644
index 0000000..f4481bf
--- /dev/null
+++ b/wifi/apex/com.android.hardware.wifi.pk8
Binary files differ
diff --git a/wifi/apex/com.android.hardware.wifi.x509.pem b/wifi/apex/com.android.hardware.wifi.x509.pem
new file mode 100644
index 0000000..c942e71
--- /dev/null
+++ b/wifi/apex/com.android.hardware.wifi.x509.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGOzCCBCOgAwIBAgIUIEueuBFEoCFmLyEvXDsKVuZeH0EwDQYJKoZIhvcNAQEL
+BQAwgasxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
+DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
+b2lkMScwJQYDVQQDDB5jb20uYW5kcm9pZC5oYXJkd2FyZS53aWZpLmFwZXgxIjAg
+BgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5kcm9pZC5jb20wIBcNMjIxMDA2MTY1MDQy
+WhgPNDc2MDA5MDExNjUwNDJaMIGrMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2Fs
+aWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9p
+ZDEQMA4GA1UECwwHQW5kcm9pZDEnMCUGA1UEAwweY29tLmFuZHJvaWQuaGFyZHdh
+cmUud2lmaS5hcGV4MSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAo4N23iL0J42qG2lt4ysD
+t6XxAKdi4sTWB6ZjFWerBm11s3yLr1KBZV82z3j2o7+EOaWa/91Mgc+aoiGYUa1f
+IweugKTrnRmrzOvtq/Wp5PGqSxsmLPPvH3wyEB/CMgAn0pqDf0WyCWJ2kAlcCkmy
+qVNFupkGFyIE6gkoc+AmJGbSTquDlL07R/8XYDicqrcgeqy9ZaCJ5FLfmbnnRb2A
+vm4Un7e5dFz5+dPaOJXf4AOMUSPUd7fuBliGYFLzcZnYQbzMktXa4XnPuSlmerwy
+EwY767L2bjRjaSgPb0Js13gZ4S4ZHZe07AV7HPlt/EzbxV/jtMgHl4xn5p0WhVnK
+MPtLsO/e7FkDPAKpT02sgUK6pVKqgBGOWm27tmTB09lscMLQeVFqwpoFq2zMUrDn
+ipDFMWRBeLrEDKx41zF3gqdPmP+SMkQYJu4OATIXOndIeo7AN9iE+N6snHkckNyE
+saCwmnzyhVAbMn/epfIQZz3zcyljA9yfOpv5jctN4es+3i0htDnoNO9ij4M5fxuP
+jtNAP3EA61nKZ5+Js0/MMQKrfwCLogPl/4vCNuuGT2rhCkhq1CLYXmb9ghvVzcPe
+BOGXNDKdB+aUTxrQUOYlHf0cRDHdU6cchrz9+QhR7t9dlibtiyCZE34xgR3klmyz
+XJ3M1r/QRihjARH7exrrwiUCAwEAAaNTMFEwHQYDVR0OBBYEFGN9tMk+4SDk7twk
+MrLjM+nRxGDJMB8GA1UdIwQYMBaAFGN9tMk+4SDk7twkMrLjM+nRxGDJMA8GA1Ud
+EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAHoTfVBRG0rVE7gkV526gwR5
+/3mXyYA57lKJhZ21fu2qfTE6WYj4DsOTZKrPIAUFv/SnzZ6Rvv7W81XV5M/1m+5R
+/1wYvWwm3FBOvvt4VDUiel0Zfc9+nwynjz1seYdXU8fNIOzBcr9hutkYdRZDkNpc
+Zcl4NG04TzyedkQ/0SyHnygmq4ZY9OUEvrNaWBFHzw2SQhYvHh8jUrqpPvoJz0Px
+avKI8bOgXTJRJ+Pk7hjXDFQY/fbE0RGivorPMLs+XHaEIb+YPyXsX4OZwowG5KL8
+txyvUsH+qZToytdPk4LCuwYBobBlr+AAg7pxOtbDW1ITDhQ9n05UFK2iUwsJecgg
+VDA0K3GuCjmGVmkw7SFRYfToCyGWah8sQCUMCCcsof7gS+dMxuWeee+sRxRJcJY+
+xR2uySe8g4ohwNjQ0zLQv7PZOKQh91yEWxRXmhPYVpiVAjpSD2zH7Vd6CJ9xji//
+5S1UrxWwQ5igvu8v5veqNAW7uXGXADnxL69HVGTLm0XDIUUOAUIG8waiVkYUo3UU
+AzAFbF7ewYMKdg7ylUYcTaMRIsKYW/3/1t3NJv2z99W4V/p8e1kRCeWMPB5C+/Lo
+b/hSWj1NF9AJ30ukBndMh6bRprq+G5NLV6OaoCLp606CMdXdT8uw9lYCt7DbQHG9
+Hw3iw61svpUwcaWfN1hI
+-----END CERTIFICATE-----
diff --git a/wifi/apex/file_contexts b/wifi/apex/file_contexts
new file mode 100644
index 0000000..812d51d
--- /dev/null
+++ b/wifi/apex/file_contexts
@@ -0,0 +1,3 @@
+(/.*)? 								u:object_r:vendor_file:s0
+/bin/hw/android\.hardware\.wifi@1.0-service			u:object_r:hal_wifi_default_exec:s0
+
diff --git a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
index 2fade4d..5c59819 100644
--- a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
@@ -122,7 +122,8 @@
 
     IHostapd::IfaceParams getIfaceParamsWithAcs(std::string iface_name) {
         // First get the settings for WithoutAcs and then make changes
-        IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithoutAcs(iface_name);
+        IHostapd::IfaceParams iface_params_1_2 =
+            getIfaceParamsWithoutAcs(iface_name);
         iface_params_1_2.V1_1.V1_0.channelParams.enableAcs = true;
         iface_params_1_2.V1_1.V1_0.channelParams.acsShouldExcludeDfs = true;
         iface_params_1_2.V1_1.V1_0.channelParams.channel = 0;
@@ -132,8 +133,10 @@
         return iface_params_1_2;
     }
 
-    IHostapd::IfaceParams getIfaceParamsWithAcsAndFreqRange(std::string iface_name) {
-        IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithAcs(iface_name);
+    IHostapd::IfaceParams getIfaceParamsWithAcsAndFreqRange(
+        std::string iface_name) {
+        IHostapd::IfaceParams iface_params_1_2 =
+            getIfaceParamsWithAcs(iface_name);
         ::android::hardware::wifi::hostapd::V1_2::IHostapd::AcsFrequencyRange
             acsFrequencyRange;
         acsFrequencyRange.start = 2412;
@@ -147,8 +150,10 @@
         return iface_params_1_2;
     }
 
-    IHostapd::IfaceParams getIfaceParamsWithAcsAndInvalidFreqRange(std::string iface_name) {
-        IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithAcsAndFreqRange(iface_name);
+    IHostapd::IfaceParams getIfaceParamsWithAcsAndInvalidFreqRange(
+        std::string iface_name) {
+        IHostapd::IfaceParams iface_params_1_2 =
+            getIfaceParamsWithAcsAndFreqRange(iface_name);
         iface_params_1_2.channelParams.acsChannelFreqRangesMhz[0].start = 222;
         iface_params_1_2.channelParams.acsChannelFreqRangesMhz[0].end = 999;
         return iface_params_1_2;
@@ -210,8 +215,10 @@
         return nw_params_1_2;
     }
 
-    IHostapd::IfaceParams getIfaceParamsWithInvalidChannel(std::string iface_name) {
-        IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithoutAcs(iface_name);
+    IHostapd::IfaceParams getIfaceParamsWithInvalidChannel(
+        std::string iface_name) {
+        IHostapd::IfaceParams iface_params_1_2 =
+            getIfaceParamsWithoutAcs(iface_name);
         iface_params_1_2.V1_1.V1_0.channelParams.channel = kIfaceInvalidChannel;
         return iface_params_1_2;
     }
@@ -237,8 +244,8 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithAcs(ifname),
-                              getPskNwParams());
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+                              getIfaceParamsWithAcs(ifname), getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -252,7 +259,8 @@
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
-                              getIfaceParamsWithAcsAndFreqRange(ifname), getPskNwParams());
+                              getIfaceParamsWithAcsAndFreqRange(ifname),
+                              getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -266,7 +274,8 @@
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
-                              getIfaceParamsWithAcsAndInvalidFreqRange(ifname), getPskNwParams());
+                              getIfaceParamsWithAcsAndInvalidFreqRange(ifname),
+                              getPskNwParams());
     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -279,8 +288,8 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithAcs(ifname),
-                              getOpenNwParams());
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+                              getIfaceParamsWithAcs(ifname), getOpenNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -292,8 +301,9 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(ifname),
-                              getPskNwParams());
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+                    getIfaceParamsWithoutAcs(ifname), getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -305,8 +315,9 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(ifname),
-                              getOpenNwParams());
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+                    getIfaceParamsWithoutAcs(ifname), getOpenNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -319,7 +330,8 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(ifname),
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+                              getIfaceParamsWithoutAcs(ifname),
                               getSaeTransitionNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
@@ -333,8 +345,9 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(ifname),
-                              getSaeNwParams());
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+                    getIfaceParamsWithoutAcs(ifname), getSaeNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -347,8 +360,9 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithAcs(ifname),
-                                  getPskNwParams());
+    auto status_1_2 =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithAcs(ifname),
+                    getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
     auto status = HIDL_INVOKE(hostapd_, removeAccessPoint, ifname);
     EXPECT_EQ(
@@ -364,8 +378,9 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(ifname),
-                                  getPskNwParams());
+    auto status_1_2 =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+                    getIfaceParamsWithoutAcs(ifname), getPskNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
     auto status = HIDL_INVOKE(hostapd_, removeAccessPoint, ifname);
     EXPECT_EQ(
@@ -381,8 +396,9 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
-                              getIfaceParamsWithInvalidChannel(ifname), getPskNwParams());
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+                    getIfaceParamsWithInvalidChannel(ifname), getPskNwParams());
     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -394,8 +410,9 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(ifname),
-                              getInvalidPskNwParams());
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+                    getIfaceParamsWithoutAcs(ifname), getInvalidPskNwParams());
     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -408,7 +425,8 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(ifname),
+    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+                              getIfaceParamsWithoutAcs(ifname),
                               getInvalidSaeTransitionNwParams());
     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
 }
@@ -422,8 +440,9 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(ifname),
-                              getInvalidSaeNwParams());
+    auto status =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+                    getIfaceParamsWithoutAcs(ifname), getInvalidSaeNwParams());
     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
 }
 
@@ -433,8 +452,8 @@
  */
 TEST_P(HostapdHidlTest, DisconnectClientWhenIfaceNotAvailable) {
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status = HIDL_INVOKE(hostapd_, forceClientDisconnect, ifname, kTestZeroMacAddr,
-                              kTestDisconnectReasonCode);
+    auto status = HIDL_INVOKE(hostapd_, forceClientDisconnect, ifname,
+                              kTestZeroMacAddr, kTestDisconnectReasonCode);
     EXPECT_EQ(HostapdStatusCode::FAILURE_IFACE_UNKNOWN, status.code);
 }
 
@@ -446,12 +465,13 @@
     if (is_1_3(hostapd_))
         GTEST_SKIP() << "Ignore addAccessPoint_1_2 on hostapd 1_3";
     std::string ifname = setupApIfaceIfNeededAndGetName();
-    auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(ifname),
-                                  getOpenNwParams());
+    auto status_1_2 =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+                    getIfaceParamsWithoutAcs(ifname), getOpenNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
 
-    status_1_2 = HIDL_INVOKE(hostapd_, forceClientDisconnect, ifname, kTestZeroMacAddr,
-                             kTestDisconnectReasonCode);
+    status_1_2 = HIDL_INVOKE(hostapd_, forceClientDisconnect, ifname,
+                             kTestZeroMacAddr, kTestDisconnectReasonCode);
     EXPECT_EQ(HostapdStatusCode::FAILURE_CLIENT_UNKNOWN, status_1_2.code);
 }
 
diff --git a/wifi/hostapd/aidl/Android.bp b/wifi/hostapd/aidl/Android.bp
index c97f8da..54895c1 100644
--- a/wifi/hostapd/aidl/Android.bp
+++ b/wifi/hostapd/aidl/Android.bp
@@ -38,9 +38,7 @@
             min_sdk_version: "30",
         },
         ndk: {
-            vndk: {
-                enabled: true,
-            },
+            gen_trace: true,
         },
     },
     versions_with_info: [
diff --git a/wifi/netlinkinterceptor/libnlinterceptor/Android.bp b/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
index 00cae32..671cd85 100644
--- a/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
+++ b/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
@@ -37,10 +37,8 @@
         "libutils",
     ],
     sanitize: {
-        address: true,
         undefined: true,
         all_undefined: true,
-        fuzzer: true,
         cfi: true,
         integer_overflow: true,
         scs: true,
diff --git a/wifi/supplicant/aidl/Android.bp b/wifi/supplicant/aidl/Android.bp
index ca0785b..9cb4e51 100644
--- a/wifi/supplicant/aidl/Android.bp
+++ b/wifi/supplicant/aidl/Android.bp
@@ -38,9 +38,7 @@
             min_sdk_version: "30",
         },
         ndk: {
-            vndk: {
-                enabled: true,
-            },
+            gen_trace: true,
         },
     },
     versions_with_info: [